* src/SDCCast.c(decorateType): better optimize '!!' and comparisons
[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       /* if already known then replace the tree : optimizer will do it
4372          but faster to do it here */
4373       if (IS_LITERAL (LTYPE (tree)))
4374         {
4375           if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
4376             return decorateType (tree->right->left, resultTypeProp);
4377           else
4378             return decorateType (tree->right->right, resultTypeProp);
4379         }
4380       else
4381         {
4382           tree->right = decorateType (tree->right, resultTypeProp);
4383           TTYPE (tree) = RTYPE (tree);
4384           TETYPE (tree) = getSpec (TTYPE (tree));
4385         }
4386       return tree;
4387
4388     case ':':
4389       /* if they don't match we have a problem */
4390       if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4391           (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4392         {
4393           werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4394           goto errorTreeReturn;
4395         }
4396
4397       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4398                                   resultType, tree->opval.op);
4399       TETYPE (tree) = getSpec (TTYPE (tree));
4400       return tree;
4401
4402
4403 #if 0 // assignment operators are converted by the parser
4404       /*------------------------------------------------------------------*/
4405       /*----------------------------*/
4406       /*    assignment operators    */
4407       /*----------------------------*/
4408     case MUL_ASSIGN:
4409     case DIV_ASSIGN:
4410       /* for these it must be both must be integral */
4411       if (!IS_ARITHMETIC (LTYPE (tree)) ||
4412           !IS_ARITHMETIC (RTYPE (tree)))
4413         {
4414           werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4415           goto errorTreeReturn;
4416         }
4417       RRVAL (tree) = 1;
4418       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4419
4420       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4421         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4422
4423       if (LRVAL (tree))
4424         {
4425           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4426           goto errorTreeReturn;
4427         }
4428       LLVAL (tree) = 1;
4429
4430       return tree;
4431
4432     case AND_ASSIGN:
4433     case OR_ASSIGN:
4434     case XOR_ASSIGN:
4435     case RIGHT_ASSIGN:
4436     case LEFT_ASSIGN:
4437       /* for these it must be both must be integral */
4438       if (!IS_INTEGRAL (LTYPE (tree)) ||
4439           !IS_INTEGRAL (RTYPE (tree)))
4440         {
4441           werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4442           goto errorTreeReturn;
4443         }
4444       RRVAL (tree) = 1;
4445       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4446
4447       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4448         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4449
4450       if (LRVAL (tree))
4451         {
4452           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4453           goto errorTreeReturn;
4454         }
4455       LLVAL (tree) = 1;
4456
4457       return tree;
4458
4459       /*------------------------------------------------------------------*/
4460       /*----------------------------*/
4461       /*    -= operator             */
4462       /*----------------------------*/
4463     case SUB_ASSIGN:
4464       if (!(IS_PTR (LTYPE (tree)) ||
4465             IS_ARITHMETIC (LTYPE (tree))))
4466         {
4467           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4468           goto errorTreeReturn;
4469         }
4470
4471       if (!(IS_PTR (RTYPE (tree)) ||
4472             IS_ARITHMETIC (RTYPE (tree))))
4473         {
4474           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4475           goto errorTreeReturn;
4476         }
4477       RRVAL (tree) = 1;
4478       TETYPE (tree) = getSpec (TTYPE (tree) =
4479                                computeType (LTYPE (tree),
4480                                             RTYPE (tree),
4481                                             RESULT_TYPE_NOPROM,
4482                                             tree->opval.op));
4483
4484       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4485         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4486
4487       if (LRVAL (tree))
4488         {
4489           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4490           goto errorTreeReturn;
4491         }
4492       LLVAL (tree) = 1;
4493
4494       return tree;
4495
4496       /*------------------------------------------------------------------*/
4497       /*----------------------------*/
4498       /*          += operator       */
4499       /*----------------------------*/
4500     case ADD_ASSIGN:
4501       /* this is not a unary operation */
4502       /* if both pointers then problem */
4503       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4504         {
4505           werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4506           goto errorTreeReturn;
4507         }
4508
4509       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4510         {
4511           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4512           goto errorTreeReturn;
4513         }
4514
4515       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4516         {
4517           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4518           goto errorTreeReturn;
4519         }
4520       RRVAL (tree) = 1;
4521       TETYPE (tree) = getSpec (TTYPE (tree) =
4522                                computeType (LTYPE (tree),
4523                                             RTYPE (tree),
4524                                             RESULT_TYPE_NOPROM,
4525                                             tree->opval.op));
4526
4527       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4528         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4529
4530       if (LRVAL (tree))
4531         {
4532           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4533           goto errorTreeReturn;
4534         }
4535
4536       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4537       tree->opval.op = '=';
4538
4539       return tree;
4540 #endif
4541
4542       /*------------------------------------------------------------------*/
4543       /*----------------------------*/
4544       /*      straight assignemnt   */
4545       /*----------------------------*/
4546     case '=':
4547       /* cannot be an aggregate */
4548       if (IS_AGGREGATE (LTYPE (tree)))
4549         {
4550           werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4551           goto errorTreeReturn;
4552         }
4553
4554       /* they should either match or be castable */
4555       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4556         {
4557           werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4558           printFromToType(RTYPE(tree),LTYPE(tree));
4559         }
4560
4561       /* if the left side of the tree is of type void
4562          then report error */
4563       if (IS_VOID (LTYPE (tree)))
4564         {
4565           werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4566           printFromToType(RTYPE(tree), LTYPE(tree));
4567         }
4568
4569       TETYPE (tree) = getSpec (TTYPE (tree) =
4570                                LTYPE (tree));
4571       RRVAL (tree) = 1;
4572       LLVAL (tree) = 1;
4573       if (!tree->initMode ) {
4574         if (IS_CONSTANT(LTYPE(tree)))
4575           werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4576       }
4577       if (LRVAL (tree))
4578         {
4579           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4580           goto errorTreeReturn;
4581         }
4582
4583       return tree;
4584
4585       /*------------------------------------------------------------------*/
4586       /*----------------------------*/
4587       /*      comma operator        */
4588       /*----------------------------*/
4589     case ',':
4590       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4591       return tree;
4592
4593       /*------------------------------------------------------------------*/
4594       /*----------------------------*/
4595       /*       function call        */
4596       /*----------------------------*/
4597     case CALL:
4598
4599       /* undo any explicit pointer derefernce; PCALL will handle it instead */
4600       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4601         {
4602           if (tree->left->opval.op == '*' && !tree->left->right)
4603             tree->left = tree->left->left;
4604         }
4605
4606       /* require a function or pointer to function */
4607       if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4608         {
4609           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4610           goto errorTreeReturn;
4611         }
4612
4613       /* if there are parms, make sure that
4614          parms are decorate / process / reverse only once */
4615       if (!tree->right ||
4616           !tree->right->decorated)
4617         {
4618           sym_link *functype;
4619           parmNumber = 1;
4620
4621           if (IS_FUNCPTR (LTYPE (tree)))
4622             {
4623               functype = LTYPE (tree)->next;
4624               processFuncPtrArgs (functype);
4625             }
4626           else
4627             functype = LTYPE (tree);
4628
4629           if (processParms (tree->left, FUNC_ARGS(functype),
4630                             &tree->right, &parmNumber, TRUE))
4631             {
4632               goto errorTreeReturn;
4633             }
4634
4635           if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4636              !IFFUNC_ISBUILTIN(functype))
4637             {
4638               reverseParms (tree->right);
4639             }
4640
4641            TTYPE (tree) = functype->next;
4642            TETYPE (tree) = getSpec (TTYPE (tree));
4643         }
4644       return tree;
4645
4646       /*------------------------------------------------------------------*/
4647       /*----------------------------*/
4648       /*     return statement       */
4649       /*----------------------------*/
4650     case RETURN:
4651       if (!tree->right)
4652         goto voidcheck;
4653
4654       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4655         {
4656           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4657           printFromToType (RTYPE(tree), currFunc->type->next);
4658           goto errorTreeReturn;
4659         }
4660
4661       if (IS_VOID (currFunc->type->next)
4662           && tree->right &&
4663           !IS_VOID (RTYPE (tree)))
4664         {
4665           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4666           goto errorTreeReturn;
4667         }
4668
4669       /* if there is going to be a casting required then add it */
4670       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4671         {
4672           tree->right =
4673             decorateType (newNode (CAST,
4674                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4675                                         tree->right),
4676                           RESULT_TYPE_NONE);
4677         }
4678
4679       RRVAL (tree) = 1;
4680       return tree;
4681
4682     voidcheck:
4683
4684       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4685         {
4686           werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4687           goto errorTreeReturn;
4688         }
4689
4690       TTYPE (tree) = TETYPE (tree) = NULL;
4691       return tree;
4692
4693       /*------------------------------------------------------------------*/
4694       /*----------------------------*/
4695       /*     switch statement       */
4696       /*----------------------------*/
4697     case SWITCH:
4698       /* the switch value must be an integer */
4699       if (!IS_INTEGRAL (LTYPE (tree)))
4700         {
4701           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4702           goto errorTreeReturn;
4703         }
4704       LRVAL (tree) = 1;
4705       TTYPE (tree) = TETYPE (tree) = NULL;
4706       return tree;
4707
4708       /*------------------------------------------------------------------*/
4709       /*----------------------------*/
4710       /* ifx Statement              */
4711       /*----------------------------*/
4712     case IFX:
4713       tree->left = backPatchLabels (tree->left,
4714                                     tree->trueLabel,
4715                                     tree->falseLabel);
4716       TTYPE (tree) = TETYPE (tree) = NULL;
4717       return tree;
4718
4719       /*------------------------------------------------------------------*/
4720       /*----------------------------*/
4721       /* for Statement              */
4722       /*----------------------------*/
4723     case FOR:
4724
4725       AST_FOR (tree, initExpr) = decorateType (
4726                   resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4727       AST_FOR (tree, condExpr) = decorateType (
4728                   resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4729       AST_FOR (tree, loopExpr) = decorateType (
4730                   resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4731
4732       /* if the for loop is reversible then
4733          reverse it otherwise do what we normally
4734          do */
4735       {
4736         symbol *sym;
4737         ast *init, *end;
4738
4739         if (isLoopReversible (tree, &sym, &init, &end))
4740           return reverseLoop (tree, sym, init, end);
4741         else
4742           return decorateType (createFor (AST_FOR (tree, trueLabel),
4743                                           AST_FOR (tree, continueLabel),
4744                                           AST_FOR (tree, falseLabel),
4745                                           AST_FOR (tree, condLabel),
4746                                           AST_FOR (tree, initExpr),
4747                                           AST_FOR (tree, condExpr),
4748                                           AST_FOR (tree, loopExpr),
4749                                           tree->left), RESULT_TYPE_NONE);
4750       }
4751     case PARAM:
4752       werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4753               "node PARAM shouldn't be processed here");
4754               /* but in processParams() */
4755       return tree;
4756     default:
4757       TTYPE (tree) = TETYPE (tree) = NULL;
4758       return tree;
4759     }
4760
4761   /* some error found this tree will be killed */
4762 errorTreeReturn:
4763   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4764   tree->opval.op = NULLOP;
4765   tree->isError = 1;
4766
4767   return tree;
4768 }
4769
4770 /*-----------------------------------------------------------------*/
4771 /* sizeofOp - processes size of operation                          */
4772 /*-----------------------------------------------------------------*/
4773 value *
4774 sizeofOp (sym_link * type)
4775 {
4776   char buff[10];
4777   int size;
4778
4779   /* make sure the type is complete and sane */
4780   checkTypeSanity(type, "(sizeof)");
4781
4782   /* get the size and convert it to character  */
4783   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4784   if (!size && !IS_VOID(type))
4785     werror (E_SIZEOF_INCOMPLETE_TYPE);
4786
4787   /* now convert into value  */
4788   return constVal (buff);
4789 }
4790
4791
4792 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4793 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4794 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4795 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4796 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4797 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4798 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4799
4800 /*-----------------------------------------------------------------*/
4801 /* backPatchLabels - change and or not operators to flow control    */
4802 /*-----------------------------------------------------------------*/
4803 static ast *
4804 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4805 {
4806
4807   if (!tree)
4808     return NULL;
4809
4810   /* while-loops insert a label between the IFX and the condition,
4811      therefore look behind the label too */
4812   if (tree->opval.op == LABEL &&
4813       tree->right &&
4814       IS_ANDORNOT (tree->right))
4815     {
4816       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4817       return tree;
4818     }
4819
4820   if (!(IS_ANDORNOT (tree)))
4821     return tree;
4822
4823   /* if this an and */
4824   if (IS_AND (tree))
4825     {
4826       static int localLbl = 0;
4827       symbol *localLabel;
4828
4829       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4830       localLabel = newSymbol (buffer, NestLevel);
4831
4832       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4833
4834       /* if left is already a IFX then just change the if true label in that */
4835       if (!IS_IFX (tree->left))
4836         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4837
4838       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4839       /* right is a IFX then just join */
4840       if (IS_IFX (tree->right))
4841         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4842
4843       tree->right = createLabel (localLabel, tree->right);
4844       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4845
4846       return newNode (NULLOP, tree->left, tree->right);
4847     }
4848
4849   /* if this is an or operation */
4850   if (IS_OR (tree))
4851     {
4852       static int localLbl = 0;
4853       symbol *localLabel;
4854
4855       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4856       localLabel = newSymbol (buffer, NestLevel);
4857
4858       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4859
4860       /* if left is already a IFX then just change the if true label in that */
4861       if (!IS_IFX (tree->left))
4862         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4863
4864       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4865       /* right is a IFX then just join */
4866       if (IS_IFX (tree->right))
4867         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4868
4869       tree->right = createLabel (localLabel, tree->right);
4870       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4871
4872       return newNode (NULLOP, tree->left, tree->right);
4873     }
4874
4875   /* change not */
4876   if (IS_NOT (tree))
4877     {
4878       /* call with exchanged labels */
4879       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4880
4881       /* if left isn't already a IFX */
4882       if (!IS_IFX (tree->left))
4883         {
4884           tree->left = newNode (IFX, tree->left, NULL);
4885           tree->left->trueLabel = falseLabel;
4886           tree->left->falseLabel = trueLabel;
4887         }
4888       return tree->left;
4889      }
4890
4891   if (IS_IFX (tree))
4892     {
4893       tree->trueLabel = trueLabel;
4894       tree->falseLabel = falseLabel;
4895     }
4896
4897   return tree;
4898 }
4899
4900
4901 /*-----------------------------------------------------------------*/
4902 /* createBlock - create expression tree for block                  */
4903 /*-----------------------------------------------------------------*/
4904 ast *
4905 createBlock (symbol * decl, ast * body)
4906 {
4907   ast *ex;
4908
4909   /* if the block has nothing */
4910   if (!body && !decl)
4911     return NULL;
4912
4913   ex = newNode (BLOCK, NULL, body);
4914   ex->values.sym = decl;
4915
4916   ex->level++;
4917   ex->lineno = 0;
4918   return ex;
4919 }
4920
4921 /*-----------------------------------------------------------------*/
4922 /* createLabel - creates the expression tree for labels            */
4923 /*-----------------------------------------------------------------*/
4924 ast *
4925 createLabel (symbol * label, ast * stmnt)
4926 {
4927   symbol *csym;
4928   char name[SDCC_NAME_MAX + 1];
4929   ast *rValue;
4930
4931   /* must create fresh symbol if the symbol name  */
4932   /* exists in the symbol table, since there can  */
4933   /* be a variable with the same name as the labl */
4934   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4935       (csym->level == label->level))
4936     label = newSymbol (label->name, label->level);
4937
4938   /* change the name before putting it in add _ */
4939   SNPRINTF(name, sizeof(name), "%s", label->name);
4940
4941   /* put the label in the LabelSymbol table    */
4942   /* but first check if a label of the same    */
4943   /* name exists                               */
4944   if ((csym = findSym (LabelTab, NULL, name)))
4945     werror (E_DUPLICATE_LABEL, label->name);
4946   else
4947     addSym (LabelTab, label, name, label->level, 0, 0);
4948
4949   label->isitmp = 1;
4950   label->islbl = 1;
4951   label->key = labelKey++;
4952   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4953   rValue->lineno = 0;
4954
4955   return rValue;
4956 }
4957
4958 /*-----------------------------------------------------------------*/
4959 /* createCase - generates the parsetree for a case statement       */
4960 /*-----------------------------------------------------------------*/
4961 ast *
4962 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4963 {
4964   char caseLbl[SDCC_NAME_MAX + 1];
4965   ast *rexpr;
4966   value *val;
4967
4968   /* if the switch statement does not exist */
4969   /* then case is out of context            */
4970   if (!swStat)
4971     {
4972       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4973       return NULL;
4974     }
4975
4976   caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
4977   /* if not a constant then error  */
4978   if (!IS_LITERAL (caseVal->ftype))
4979     {
4980       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4981       return NULL;
4982     }
4983
4984   /* if not a integer than error */
4985   if (!IS_INTEGRAL (caseVal->ftype))
4986     {
4987       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4988       return NULL;
4989     }
4990
4991   /* find the end of the switch values chain   */
4992   if (!(val = swStat->values.switchVals.swVals))
4993     swStat->values.switchVals.swVals = caseVal->opval.val;
4994   else
4995     {
4996       /* also order the cases according to value */
4997       value *pval = NULL;
4998       int cVal = (int) floatFromVal (caseVal->opval.val);
4999       while (val && (int) floatFromVal (val) < cVal)
5000         {
5001           pval = val;
5002           val = val->next;
5003         }
5004
5005       /* if we reached the end then */
5006       if (!val)
5007         {
5008           pval->next = caseVal->opval.val;
5009         }
5010       else if ((int) floatFromVal (val) == cVal)
5011         {
5012           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5013                     "case");
5014           return NULL;
5015         }
5016       else
5017         {
5018           /* we found a value greater than */
5019           /* the current value we must add this */
5020           /* before the value */
5021           caseVal->opval.val->next = val;
5022
5023           /* if this was the first in chain */
5024           if (swStat->values.switchVals.swVals == val)
5025             swStat->values.switchVals.swVals =
5026               caseVal->opval.val;
5027           else
5028             pval->next = caseVal->opval.val;
5029         }
5030
5031     }
5032
5033   /* create the case label   */
5034   SNPRINTF(caseLbl, sizeof(caseLbl),
5035            "_case_%d_%d",
5036            swStat->values.switchVals.swNum,
5037            (int) floatFromVal (caseVal->opval.val));
5038
5039   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5040   rexpr->lineno = 0;
5041   return rexpr;
5042 }
5043
5044 /*-----------------------------------------------------------------*/
5045 /* createDefault - creates the parse tree for the default statement */
5046 /*-----------------------------------------------------------------*/
5047 ast *
5048 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5049 {
5050   char defLbl[SDCC_NAME_MAX + 1];
5051
5052   /* if the switch statement does not exist */
5053   /* then case is out of context            */
5054   if (!swStat)
5055     {
5056       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5057       return NULL;
5058     }
5059
5060   if (swStat->values.switchVals.swDefault)
5061     {
5062       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5063                 "default");
5064       return NULL;
5065     }
5066
5067   /* turn on the default flag   */
5068   swStat->values.switchVals.swDefault = 1;
5069
5070   /* create the label  */
5071   SNPRINTF (defLbl, sizeof(defLbl),
5072             "_default_%d", swStat->values.switchVals.swNum);
5073   return createLabel (newSymbol (defLbl, 0), stmnt);
5074 }
5075
5076 /*-----------------------------------------------------------------*/
5077 /* createIf - creates the parsetree for the if statement           */
5078 /*-----------------------------------------------------------------*/
5079 ast *
5080 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5081 {
5082   static int Lblnum = 0;
5083   ast *ifTree;
5084   symbol *ifTrue, *ifFalse, *ifEnd;
5085
5086   /* if neither exists */
5087   if (!elseBody && !ifBody) {
5088     // if there are no side effects (i++, j() etc)
5089     if (!hasSEFcalls(condAst)) {
5090       return condAst;
5091     }
5092   }
5093
5094   /* create the labels */
5095   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5096   ifFalse = newSymbol (buffer, NestLevel);
5097   /* if no else body then end == false */
5098   if (!elseBody)
5099     ifEnd = ifFalse;
5100   else
5101     {
5102       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5103       ifEnd = newSymbol (buffer, NestLevel);
5104     }
5105
5106   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5107   ifTrue = newSymbol (buffer, NestLevel);
5108
5109   Lblnum++;
5110
5111   /* attach the ifTrue label to the top of it body */
5112   ifBody = createLabel (ifTrue, ifBody);
5113   /* attach a goto end to the ifBody if else is present */
5114   if (elseBody)
5115     {
5116       ifBody = newNode (NULLOP, ifBody,
5117                         newNode (GOTO,
5118                                  newAst_VALUE (symbolVal (ifEnd)),
5119                                  NULL));
5120       /* put the elseLabel on the else body */
5121       elseBody = createLabel (ifFalse, elseBody);
5122       /* out the end at the end of the body */
5123       elseBody = newNode (NULLOP,
5124                           elseBody,
5125                           createLabel (ifEnd, NULL));
5126     }
5127   else
5128     {
5129       ifBody = newNode (NULLOP, ifBody,
5130                         createLabel (ifFalse, NULL));
5131     }
5132   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5133   if (IS_IFX (condAst))
5134     ifTree = condAst;
5135   else
5136     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5137
5138   return newNode (NULLOP, ifTree,
5139                   newNode (NULLOP, ifBody, elseBody));
5140
5141 }
5142
5143 /*-----------------------------------------------------------------*/
5144 /* createDo - creates parse tree for do                            */
5145 /*        _dobody_n:                                               */
5146 /*            statements                                           */
5147 /*        _docontinue_n:                                           */
5148 /*            condition_expression +-> trueLabel -> _dobody_n      */
5149 /*                                 |                               */
5150 /*                                 +-> falseLabel-> _dobreak_n     */
5151 /*        _dobreak_n:                                              */
5152 /*-----------------------------------------------------------------*/
5153 ast *
5154 createDo (symbol * trueLabel, symbol * continueLabel,
5155           symbol * falseLabel, ast * condAst, ast * doBody)
5156 {
5157   ast *doTree;
5158
5159
5160   /* if the body does not exist then it is simple */
5161   if (!doBody)
5162     {
5163       condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5164       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5165                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5166       doTree->trueLabel = continueLabel;
5167       doTree->falseLabel = NULL;
5168
5169       doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5170       return doTree;
5171     }
5172
5173   /* otherwise we have a body */
5174   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5175
5176   /* attach the body label to the top */
5177   doBody = createLabel (trueLabel, doBody);
5178   /* attach the continue label to end of body */
5179   doBody = newNode (NULLOP, doBody,
5180                     createLabel (continueLabel, NULL));
5181
5182   /* now put the break label at the end */
5183   if (IS_IFX (condAst))
5184     doTree = condAst;
5185   else
5186     doTree = newIfxNode (condAst, trueLabel, falseLabel);
5187
5188   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5189
5190   /* putting it together */
5191   return newNode (NULLOP, doBody, doTree);
5192 }
5193
5194 /*-----------------------------------------------------------------*/
5195 /* createFor - creates parse tree for 'for' statement              */
5196 /*        initExpr                                                 */
5197 /*   _forcond_n:                                                   */
5198 /*        condExpr  +-> trueLabel -> _forbody_n                    */
5199 /*                  |                                              */
5200 /*                  +-> falseLabel-> _forbreak_n                   */
5201 /*   _forbody_n:                                                   */
5202 /*        statements                                               */
5203 /*   _forcontinue_n:                                               */
5204 /*        loopExpr                                                 */
5205 /*        goto _forcond_n ;                                        */
5206 /*   _forbreak_n:                                                  */
5207 /*-----------------------------------------------------------------*/
5208 ast *
5209 createFor (symbol * trueLabel, symbol * continueLabel,
5210            symbol * falseLabel, symbol * condLabel,
5211            ast * initExpr, ast * condExpr, ast * loopExpr,
5212            ast * forBody)
5213 {
5214   ast *forTree;
5215
5216   /* if loopexpression not present then we can generate it */
5217   /* the same way as a while */
5218   if (!loopExpr)
5219     return newNode (NULLOP, initExpr,
5220                     createWhile (trueLabel, continueLabel,
5221                                  falseLabel, condExpr, forBody));
5222   /* vanilla for statement */
5223   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5224
5225   if (condExpr && !IS_IFX (condExpr))
5226     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5227
5228
5229   /* attach condition label to condition */
5230   condExpr = createLabel (condLabel, condExpr);
5231
5232   /* attach body label to body */
5233   forBody = createLabel (trueLabel, forBody);
5234
5235   /* attach continue to forLoop expression & attach */
5236   /* goto the forcond @ and of loopExpression       */
5237   loopExpr = createLabel (continueLabel,
5238                           newNode (NULLOP,
5239                                    loopExpr,
5240                                    newNode (GOTO,
5241                                        newAst_VALUE (symbolVal (condLabel)),
5242                                             NULL)));
5243   /* now start putting them together */
5244   forTree = newNode (NULLOP, initExpr, condExpr);
5245   forTree = newNode (NULLOP, forTree, forBody);
5246   forTree = newNode (NULLOP, forTree, loopExpr);
5247   /* finally add the break label */
5248   forTree = newNode (NULLOP, forTree,
5249                      createLabel (falseLabel, NULL));
5250   return forTree;
5251 }
5252
5253 /*-----------------------------------------------------------------*/
5254 /* createWhile - creates parse tree for while statement            */
5255 /*               the while statement will be created as follows    */
5256 /*                                                                 */
5257 /*      _while_continue_n:                                         */
5258 /*            condition_expression +-> trueLabel -> _while_boby_n  */
5259 /*                                 |                               */
5260 /*                                 +-> falseLabel -> _while_break_n */
5261 /*      _while_body_n:                                             */
5262 /*            statements                                           */
5263 /*            goto _while_continue_n                               */
5264 /*      _while_break_n:                                            */
5265 /*-----------------------------------------------------------------*/
5266 ast *
5267 createWhile (symbol * trueLabel, symbol * continueLabel,
5268              symbol * falseLabel, ast * condExpr, ast * whileBody)
5269 {
5270   ast *whileTree;
5271
5272   /* put the continue label */
5273   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5274   condExpr = createLabel (continueLabel, condExpr);
5275   condExpr->lineno = 0;
5276
5277   /* put the body label in front of the body */
5278   whileBody = createLabel (trueLabel, whileBody);
5279   whileBody->lineno = 0;
5280   /* put a jump to continue at the end of the body */
5281   /* and put break label at the end of the body */
5282   whileBody = newNode (NULLOP,
5283                        whileBody,
5284                        newNode (GOTO,
5285                                 newAst_VALUE (symbolVal (continueLabel)),
5286                                 createLabel (falseLabel, NULL)));
5287
5288   /* put it all together */
5289   if (IS_IFX (condExpr))
5290     whileTree = condExpr;
5291   else
5292     {
5293       whileTree = newNode (IFX, condExpr, NULL);
5294       /* put the true & false labels in place */
5295       whileTree->trueLabel = trueLabel;
5296       whileTree->falseLabel = falseLabel;
5297     }
5298
5299   return newNode (NULLOP, whileTree, whileBody);
5300 }
5301
5302 /*-----------------------------------------------------------------*/
5303 /* isShiftRightLitVal _BitAndLitVal - helper function              */
5304 /*-----------------------------------------------------------------*/
5305 static ast *
5306 isShiftRightLitVal_BitAndLitVal (ast * tree)
5307 {
5308   /* if this is not a bit and */
5309   if (!IS_BITAND (tree))
5310     return NULL;
5311
5312   /* will look for tree of the form
5313      ( expr >> litval2) & litval1 */
5314   if (!IS_AST_LIT_VALUE (tree->right))
5315     return NULL;
5316
5317   if (!IS_RIGHT_OP (tree->left))
5318     return NULL;
5319
5320   if (!IS_AST_LIT_VALUE (tree->left->right))
5321     return NULL;
5322
5323   return tree->left->left;
5324 }
5325
5326 /*-----------------------------------------------------------------*/
5327 /* isBitAndPowOf2 - helper function                                */
5328 /*-----------------------------------------------------------------*/
5329 static int
5330 isBitAndPow2 (ast * tree)
5331 {
5332   /* if this is not a bit and */
5333   if (!IS_BITAND (tree))
5334     return -1;
5335
5336   /* will look for tree of the form
5337      ( expr & (1 << litval) */
5338   if (!IS_AST_LIT_VALUE (tree->right))
5339     return -1;
5340
5341   return powof2 ((TYPE_TARGET_ULONG)AST_LIT_VALUE (tree->right));
5342 }
5343
5344 /*-----------------------------------------------------------------*/
5345 /* optimizeGetHbit - get highest order bit of the expression       */
5346 /*-----------------------------------------------------------------*/
5347 ast *
5348 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5349 {
5350   int i, j;
5351   ast * expr;
5352
5353   expr = isShiftRightLitVal_BitAndLitVal(tree);
5354   if (expr)
5355     {
5356       if ((AST_LIT_VALUE (tree->right) != 1) ||
5357           ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
5358           (j = (getSize (TTYPE (expr)) * 8 - 1))))
5359         expr = NULL;
5360     }
5361   if (!expr && (resultType == RESULT_TYPE_BIT))
5362     {
5363       expr = tree->left;
5364       if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5365         expr = NULL;
5366     }
5367   if (!expr)
5368     return tree;
5369
5370   /* make sure the port supports GETHBIT */
5371   if (port->hasExtBitOp
5372       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5373     return tree;
5374
5375   return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5376 }
5377
5378 /*-----------------------------------------------------------------*/
5379 /* optimizeGetAbit - get a single bit of the expression            */
5380 /*-----------------------------------------------------------------*/
5381 ast *
5382 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5383 {
5384   ast * expr;
5385   ast * count = NULL;
5386
5387   expr = isShiftRightLitVal_BitAndLitVal(tree);
5388   if (expr)
5389     {
5390   if (AST_LIT_VALUE (tree->right) != 1)
5391         expr = NULL;
5392       count = tree->left->right;
5393     }
5394   if (!expr && (resultType == RESULT_TYPE_BIT))
5395     {
5396       int p2 = isBitAndPow2 (tree);
5397       if (p2 >= 0)
5398         {
5399           expr = tree->left;
5400           count = newAst_VALUE (valueFromLit (p2));
5401         }
5402     }
5403   if (!expr)
5404     return tree;
5405
5406   /* make sure the port supports GETABIT */
5407   if (port->hasExtBitOp
5408       && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5409     return tree;
5410
5411   return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5412
5413 }
5414
5415 /*-----------------------------------------------------------------*/
5416 /* optimizeGetByte - get a byte of the expression                  */
5417 /*-----------------------------------------------------------------*/
5418 ast *
5419 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5420 {
5421   unsigned int i = 0;
5422   ast * expr;
5423   ast * count = NULL;
5424
5425   expr = isShiftRightLitVal_BitAndLitVal(tree);
5426   if (expr)
5427     {
5428       i = (unsigned int) AST_LIT_VALUE (tree->left->right);
5429       count = tree->left->right;
5430       if (AST_LIT_VALUE (tree->right) != 0xFF)
5431         expr = NULL;
5432     }
5433   if (!expr && resultType == RESULT_TYPE_CHAR)
5434     {
5435       /* if this is a right shift over a multiple of 8 */
5436       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5437         {
5438           i = (unsigned int) AST_LIT_VALUE (tree->right);
5439           count = tree->right;
5440             expr = tree->left;
5441         }
5442     }
5443   if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5444     return tree;
5445
5446   /* make sure the port supports GETBYTE */
5447   if (port->hasExtBitOp
5448       && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5449     return tree;
5450
5451   return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5452 }
5453
5454 /*-----------------------------------------------------------------*/
5455 /* optimizeGetWord - get two bytes of the expression               */
5456 /*-----------------------------------------------------------------*/
5457 ast *
5458 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5459 {
5460   unsigned int i = 0;
5461   ast * expr;
5462   ast * count = NULL;
5463
5464   expr = isShiftRightLitVal_BitAndLitVal(tree);
5465   if (expr)
5466     {
5467       i = (unsigned int) AST_LIT_VALUE (tree->left->right);
5468       count = tree->left->right;
5469       if (AST_LIT_VALUE (tree->right) != 0xFFFF)
5470         expr = NULL;
5471     }
5472   if (!expr && resultType == RESULT_TYPE_INT)
5473     {
5474       /* if this is a right shift over a multiple of 8 */
5475       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5476         {
5477           i = (unsigned int) AST_LIT_VALUE (tree->right);
5478           count = tree->right;
5479             expr = tree->left;
5480         }
5481     }
5482   if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5483     return tree;
5484
5485   /* make sure the port supports GETWORD */
5486   if (port->hasExtBitOp
5487       && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5488     return tree;
5489
5490   return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5491 }
5492
5493 /*-----------------------------------------------------------------*/
5494 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
5495 /*-----------------------------------------------------------------*/
5496 ast *
5497 optimizeRRCRLC (ast * root)
5498 {
5499   /* will look for trees of the form
5500      (?expr << 1) | (?expr >> 7) or
5501      (?expr >> 7) | (?expr << 1) will make that
5502      into a RLC : operation ..
5503      Will also look for
5504      (?expr >> 1) | (?expr << 7) or
5505      (?expr << 7) | (?expr >> 1) will make that
5506      into a RRC operation
5507      note : by 7 I mean (number of bits required to hold the
5508      variable -1 ) */
5509   /* if the root operation is not a | operation then not */
5510   if (!IS_BITOR (root))
5511     return root;
5512
5513   /* I have to think of a better way to match patterns this sucks */
5514   /* that aside let's start looking for the first case : I use a
5515      negative check a lot to improve the efficiency */
5516   /* (?expr << 1) | (?expr >> 7) */
5517   if (IS_LEFT_OP (root->left) &&
5518       IS_RIGHT_OP (root->right))
5519     {
5520
5521       if (!SPEC_USIGN (TETYPE (root->left->left)))
5522         return root;
5523
5524       if (!IS_AST_LIT_VALUE (root->left->right) ||
5525           !IS_AST_LIT_VALUE (root->right->right))
5526         goto tryNext0;
5527
5528       /* make sure it is the same expression */
5529       if (!isAstEqual (root->left->left,
5530                        root->right->left))
5531         goto tryNext0;
5532
5533       if (AST_LIT_VALUE (root->left->right) != 1)
5534         goto tryNext0;
5535
5536       if (AST_LIT_VALUE (root->right->right) !=
5537           (getSize (TTYPE (root->left->left)) * 8 - 1))
5538         goto tryNext0;
5539
5540       /* make sure the port supports RLC */
5541       if (port->hasExtBitOp
5542           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5543         return root;
5544
5545       /* whew got the first case : create the AST */
5546       return newNode (RLC, root->left->left, NULL);
5547     }
5548
5549 tryNext0:
5550   /* check for second case */
5551   /* (?expr >> 7) | (?expr << 1) */
5552   if (IS_LEFT_OP (root->right) &&
5553       IS_RIGHT_OP (root->left))
5554     {
5555
5556       if (!SPEC_USIGN (TETYPE (root->left->left)))
5557         return root;
5558
5559       if (!IS_AST_LIT_VALUE (root->left->right) ||
5560           !IS_AST_LIT_VALUE (root->right->right))
5561         goto tryNext1;
5562
5563       /* make sure it is the same symbol */
5564       if (!isAstEqual (root->left->left,
5565                        root->right->left))
5566         goto tryNext1;
5567
5568       if (AST_LIT_VALUE (root->right->right) != 1)
5569         goto tryNext1;
5570
5571       if (AST_LIT_VALUE (root->left->right) !=
5572           (getSize (TTYPE (root->left->left)) * 8 - 1))
5573         goto tryNext1;
5574
5575       /* make sure the port supports RLC */
5576       if (port->hasExtBitOp
5577           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5578         return root;
5579
5580       /* whew got the first case : create the AST */
5581       return newNode (RLC, root->left->left, NULL);
5582
5583     }
5584
5585 tryNext1:
5586   /* third case for RRC */
5587   /*  (?symbol >> 1) | (?symbol << 7) */
5588   if (IS_LEFT_OP (root->right) &&
5589       IS_RIGHT_OP (root->left))
5590     {
5591
5592       if (!SPEC_USIGN (TETYPE (root->left->left)))
5593         return root;
5594
5595       if (!IS_AST_LIT_VALUE (root->left->right) ||
5596           !IS_AST_LIT_VALUE (root->right->right))
5597         goto tryNext2;
5598
5599       /* make sure it is the same symbol */
5600       if (!isAstEqual (root->left->left,
5601                        root->right->left))
5602         goto tryNext2;
5603
5604       if (AST_LIT_VALUE (root->left->right) != 1)
5605         goto tryNext2;
5606
5607       if (AST_LIT_VALUE (root->right->right) !=
5608           (getSize (TTYPE (root->left->left)) * 8 - 1))
5609         goto tryNext2;
5610
5611       /* make sure the port supports RRC */
5612       if (port->hasExtBitOp
5613           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5614         return root;
5615
5616       /* whew got the first case : create the AST */
5617       return newNode (RRC, root->left->left, NULL);
5618
5619     }
5620 tryNext2:
5621   /* fourth and last case for now */
5622   /* (?symbol << 7) | (?symbol >> 1) */
5623   if (IS_RIGHT_OP (root->right) &&
5624       IS_LEFT_OP (root->left))
5625     {
5626
5627       if (!SPEC_USIGN (TETYPE (root->left->left)))
5628         return root;
5629
5630       if (!IS_AST_LIT_VALUE (root->left->right) ||
5631           !IS_AST_LIT_VALUE (root->right->right))
5632         return root;
5633
5634       /* make sure it is the same symbol */
5635       if (!isAstEqual (root->left->left,
5636                        root->right->left))
5637         return root;
5638
5639       if (AST_LIT_VALUE (root->right->right) != 1)
5640         return root;
5641
5642       if (AST_LIT_VALUE (root->left->right) !=
5643           (getSize (TTYPE (root->left->left)) * 8 - 1))
5644         return root;
5645
5646       /* make sure the port supports RRC */
5647       if (port->hasExtBitOp
5648           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5649         return root;
5650
5651       /* whew got the first case : create the AST */
5652       return newNode (RRC, root->left->left, NULL);
5653
5654     }
5655
5656   /* not found return root */
5657   return root;
5658 }
5659
5660 /*-----------------------------------------------------------------*/
5661 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
5662 /*-----------------------------------------------------------------*/
5663 ast *
5664 optimizeSWAP (ast * root)
5665 {
5666   /* will look for trees of the form
5667      (?expr << 4) | (?expr >> 4) or
5668      (?expr >> 4) | (?expr << 4) will make that
5669      into a SWAP : operation ..
5670      note : by 4 I mean (number of bits required to hold the
5671      variable /2 ) */
5672   /* if the root operation is not a | operation then not */
5673   if (!IS_BITOR (root))
5674     return root;
5675
5676   /* (?expr << 4) | (?expr >> 4) */
5677   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5678       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5679     {
5680
5681       if (!SPEC_USIGN (TETYPE (root->left->left)))
5682         return root;
5683
5684       if (!IS_AST_LIT_VALUE (root->left->right) ||
5685           !IS_AST_LIT_VALUE (root->right->right))
5686         return root;
5687
5688       /* make sure it is the same expression */
5689       if (!isAstEqual (root->left->left,
5690                        root->right->left))
5691         return root;
5692
5693       if (AST_LIT_VALUE (root->left->right) !=
5694           (getSize (TTYPE (root->left->left)) * 4))
5695         return root;
5696
5697       if (AST_LIT_VALUE (root->right->right) !=
5698           (getSize (TTYPE (root->left->left)) * 4))
5699         return root;
5700
5701       /* make sure the port supports SWAP */
5702       if (port->hasExtBitOp
5703           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5704         return root;
5705
5706       /* found it : create the AST */
5707       return newNode (SWAP, root->left->left, NULL);
5708     }
5709
5710
5711   /* not found return root */
5712   return root;
5713 }
5714
5715 /*-----------------------------------------------------------------*/
5716 /* optimizeCompare - optimizes compares for bit variables          */
5717 /*-----------------------------------------------------------------*/
5718 static ast *
5719 optimizeCompare (ast * root)
5720 {
5721   ast *optExpr = NULL;
5722   value *vleft;
5723   value *vright;
5724   unsigned int litValue;
5725
5726   /* if nothing then return nothing */
5727   if (!root)
5728     return NULL;
5729
5730   /* if not a compare op then do leaves */
5731   if (!IS_COMPARE_OP (root))
5732     {
5733       root->left = optimizeCompare (root->left);
5734       root->right = optimizeCompare (root->right);
5735       return root;
5736     }
5737
5738   /* if left & right are the same then depending
5739      of the operation do */
5740   if (isAstEqual (root->left, root->right))
5741     {
5742       switch (root->opval.op)
5743         {
5744         case '>':
5745         case '<':
5746         case NE_OP:
5747           optExpr = newAst_VALUE (constVal ("0"));
5748           break;
5749         case GE_OP:
5750         case LE_OP:
5751         case EQ_OP:
5752           optExpr = newAst_VALUE (constVal ("1"));
5753           break;
5754         }
5755
5756       return decorateType (optExpr, RESULT_TYPE_NONE);
5757     }
5758
5759   vleft = (root->left->type == EX_VALUE ?
5760            root->left->opval.val : NULL);
5761
5762   vright = (root->right->type == EX_VALUE ?
5763             root->right->opval.val : NULL);
5764
5765   /* if left is a BITVAR in BITSPACE */
5766   /* and right is a LITERAL then     */
5767   /* optimize else do nothing        */
5768   if (vleft && vright &&
5769       IS_BITVAR (vleft->etype) &&
5770       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5771       IS_LITERAL (vright->etype))
5772     {
5773
5774       /* if right side > 1 then comparison may never succeed */
5775       if ((litValue = (int) floatFromVal (vright)) > 1)
5776         {
5777           werror (W_BAD_COMPARE);
5778           goto noOptimize;
5779         }
5780
5781       if (litValue)
5782         {
5783           switch (root->opval.op)
5784             {
5785             case '>':           /* bit value greater than 1 cannot be */
5786               werror (W_BAD_COMPARE);
5787               goto noOptimize;
5788               break;
5789
5790             case '<':           /* bit value < 1 means 0 */
5791             case NE_OP:
5792               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5793               break;
5794
5795             case LE_OP: /* bit value <= 1 means no check */
5796               optExpr = newAst_VALUE (vright);
5797               break;
5798
5799             case GE_OP: /* bit value >= 1 means only check for = */
5800             case EQ_OP:
5801               optExpr = newAst_VALUE (vleft);
5802               break;
5803             }
5804         }
5805       else
5806         {                       /* literal is zero */
5807           switch (root->opval.op)
5808             {
5809             case '<':           /* bit value < 0 cannot be */
5810               werror (W_BAD_COMPARE);
5811               goto noOptimize;
5812               break;
5813
5814             case '>':           /* bit value > 0 means 1 */
5815             case NE_OP:
5816               optExpr = newAst_VALUE (vleft);
5817               break;
5818
5819             case LE_OP: /* bit value <= 0 means no check */
5820             case GE_OP: /* bit value >= 0 means no check */
5821               werror (W_BAD_COMPARE);
5822               goto noOptimize;
5823               break;
5824
5825             case EQ_OP: /* bit == 0 means ! of bit */
5826               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5827               break;
5828             }
5829         }
5830       return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5831     }                           /* end-of-if of BITVAR */
5832
5833 noOptimize:
5834   return root;
5835 }
5836
5837 /*-----------------------------------------------------------------*/
5838 /* addSymToBlock : adds the symbol to the first block we find      */
5839 /*-----------------------------------------------------------------*/
5840 void
5841 addSymToBlock (symbol * sym, ast * tree)
5842 {
5843   /* reached end of tree or a leaf */
5844   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5845     return;
5846
5847   /* found a block */
5848   if (IS_AST_OP (tree) &&
5849       tree->opval.op == BLOCK)
5850     {
5851
5852       symbol *lsym = copySymbol (sym);
5853
5854       lsym->next = AST_VALUES (tree, sym);
5855       AST_VALUES (tree, sym) = lsym;
5856       return;
5857     }
5858
5859   addSymToBlock (sym, tree->left);
5860   addSymToBlock (sym, tree->right);
5861 }
5862
5863 /*-----------------------------------------------------------------*/
5864 /* processRegParms - do processing for register parameters         */
5865 /*-----------------------------------------------------------------*/
5866 static void
5867 processRegParms (value * args, ast * body)
5868 {
5869   while (args)
5870     {
5871       if (IS_REGPARM (args->etype))
5872         addSymToBlock (args->sym, body);
5873       args = args->next;
5874     }
5875 }
5876
5877 /*-----------------------------------------------------------------*/
5878 /* resetParmKey - resets the operandkeys for the symbols           */
5879 /*-----------------------------------------------------------------*/
5880 DEFSETFUNC (resetParmKey)
5881 {
5882   symbol *sym = item;
5883
5884   sym->key = 0;
5885   sym->defs = NULL;
5886   sym->uses = NULL;
5887   sym->remat = 0;
5888   return 1;
5889 }
5890
5891
5892
5893 /*------------------------------------------------------------------*/
5894 /* fixupInlineLabel - change a label in an inlined function so that */
5895 /*                    it is always unique no matter how many times  */
5896 /*                    the function is inlined.                      */
5897 /*------------------------------------------------------------------*/
5898 static void
5899 fixupInlineLabel (symbol * sym)
5900 {
5901   char name[SDCC_NAME_MAX + 1];
5902   
5903   SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5904   strcpy (sym->name, name);
5905 }
5906
5907
5908 /*------------------------------------------------------------------*/
5909 /* copyAstLoc - copy location information (file, line, block, etc.) */
5910 /*              from one ast node to another                        */
5911 /*------------------------------------------------------------------*/
5912 static void
5913 copyAstLoc (ast * dest, ast * src)
5914 {
5915   dest->lineno = src->lineno;
5916   dest->filename = src->filename;
5917   dest->level = src->level;
5918   dest->block = src->block;
5919   dest->seqPoint = src->seqPoint;
5920   
5921 }
5922
5923
5924 /*-----------------------------------------------------------------*/
5925 /* fixupInline - perform various fixups on an inline function tree */
5926 /*               to take into account that it is no longer a       */
5927 /*               stand-alone function.                             */
5928 /*-----------------------------------------------------------------*/
5929 static void
5930 fixupInline (ast * tree, int level)
5931 {
5932   tree->block = currBlockno;
5933
5934   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
5935     {
5936       symbol * decls;
5937
5938       currBlockno++;
5939       level++;
5940
5941       /* Add any declared variables back into the symbol table */
5942       decls = tree->values.sym;
5943       while (decls)
5944         {
5945           decls->level = level;
5946           decls->block = currBlockno;
5947           addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
5948           decls = decls->next;
5949         }
5950     }
5951
5952   tree->level = level;
5953
5954   /* Update symbols */
5955   if (IS_AST_VALUE (tree) &&
5956       tree->opval.val->sym)
5957     {
5958       symbol * sym = tree->opval.val->sym;
5959
5960       sym->level = level;
5961       sym->block = currBlockno;
5962
5963       sym->reqv = NULL;
5964       SYM_SPIL_LOC (sym) = NULL;
5965       sym->key = 0;
5966
5967       /* If the symbol is a label, we need to renumber it */
5968       if (sym->islbl)
5969         fixupInlineLabel (sym);
5970     }
5971
5972   /* Update IFX target labels */
5973   if (tree->type == EX_OP && tree->opval.op == IFX)
5974     {
5975       if (tree->trueLabel)
5976         fixupInlineLabel (tree->trueLabel);
5977       if (tree->falseLabel)
5978         fixupInlineLabel (tree->falseLabel);
5979     }
5980
5981   /* Replace RETURN with optional assignment and a GOTO to the end */
5982   /* of the inlined function */
5983   if (tree->type == EX_OP && tree->opval.op == RETURN)
5984     {
5985       ast * assignTree = NULL;
5986       ast * gotoTree;
5987
5988       if (inlineState.retsym && tree->right)
5989         {
5990           assignTree = newNode ('=',
5991                                 newAst_VALUE (symbolVal (inlineState.retsym)),
5992                                 tree->right);
5993           copyAstLoc (assignTree, tree);
5994         }
5995
5996       gotoTree = newNode (GOTO,
5997                           newAst_VALUE (symbolVal (inlineState.retlab)),
5998                           NULL);
5999       copyAstLoc (gotoTree, tree);
6000
6001       tree->opval.op = NULLOP;
6002       tree->left = assignTree;
6003       tree->right = gotoTree;
6004     }
6005
6006    /* Update any children */
6007    if (tree->left)
6008       fixupInline (tree->left, level);
6009    if (tree->right)
6010       fixupInline (tree->right, level);
6011
6012   if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6013     {
6014       symbol * label = tree->left->opval.val->sym;
6015
6016       label->key = labelKey++;
6017       /* Add this label back into the symbol table */
6018       addSym (LabelTab, label, label->name, label->level, 0, 0);
6019     }
6020
6021
6022   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6023     {
6024       level--;
6025     }
6026 }
6027
6028 /*-----------------------------------------------------------------*/
6029 /* inlineAddDecl - add a variable declaration to an ast block. It  */
6030 /*                 is also added to the symbol table if addSymTab  */
6031 /*                 is nonzero.                                     */
6032 /*-----------------------------------------------------------------*/
6033 static void
6034 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6035 {
6036   sym->reqv = NULL;
6037   SYM_SPIL_LOC (sym) = NULL;
6038   sym->key = 0;
6039   if (block != NULL)
6040     {
6041       symbol **decl = &(block->values.sym);
6042
6043       sym->level = block->level;
6044       sym->block = block->block;
6045
6046       while (*decl)
6047         {
6048           if (strcmp ((*decl)->name, sym->name) == 0)
6049             return;
6050           decl = &( (*decl)->next );
6051         }
6052
6053       *decl = sym;
6054
6055       if (addSymTab)
6056         addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6057
6058     }
6059 }
6060
6061
6062 /*-----------------------------------------------------------------*/
6063 /* inlineTempVar - create a temporary variable for inlining        */
6064 /*-----------------------------------------------------------------*/
6065 static symbol *
6066 inlineTempVar (sym_link * type, int level)
6067 {
6068   symbol * sym;
6069
6070   sym = newSymbol (genSymName(level), level );
6071   sym->type = copyLinkChain (type);
6072   sym->etype = getSpec(sym->type);
6073   SPEC_SCLS (sym->etype) = S_AUTO;
6074   SPEC_OCLS (sym->etype) = NULL;
6075   SPEC_EXTR (sym->etype) = 0;
6076   SPEC_STAT (sym->etype) = 0;
6077   if IS_SPEC (sym->type)
6078     SPEC_VOLATILE (sym->type) = 0;
6079   else
6080     DCL_PTR_VOLATILE (sym->type) = 0;
6081   SPEC_ABSA (sym->etype) = 0;
6082
6083   return sym;
6084 }
6085
6086
6087 /*-----------------------------------------------------------------*/
6088 /* inlineFindParmRecurse - recursive function for inlineFindParm   */
6089 /*-----------------------------------------------------------------*/
6090 static ast *
6091 inlineFindParmRecurse (ast * parms, int *index)
6092 {
6093   if (!parms)
6094     return NULL;
6095
6096   if (parms->type == EX_OP && parms->opval.op == PARAM)
6097   {
6098     ast * p;
6099
6100     p=inlineFindParmRecurse (parms->left, index);
6101     if (p)
6102       return p;
6103     p=inlineFindParmRecurse (parms->right, index);
6104     if (p)
6105       return p;
6106   }
6107   if (!*index)
6108     return parms;
6109   (*index)--;
6110   return NULL;
6111 }
6112
6113
6114 /*-----------------------------------------------------------------*/
6115 /* inlineFindParm - search an ast tree of parameters to find one   */
6116 /*                  at a particular index (0=first parameter).     */
6117 /*                  Returns NULL if not found.                     */
6118 /*-----------------------------------------------------------------*/
6119 static ast *
6120 inlineFindParm (ast * parms, int index)
6121 {
6122   return inlineFindParmRecurse (parms, &index);
6123 }
6124
6125
6126 /*-----------------------------------------------------------------*/
6127 /* expandInlineFuncs - replace calls to inline functions with the  */
6128 /*                     function itself                             */
6129 /*-----------------------------------------------------------------*/
6130 static void
6131 expandInlineFuncs (ast * tree, ast * block)
6132 {
6133   if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6134       && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6135     {
6136       symbol * func = tree->left->opval.val->sym;
6137       symbol * csym;
6138
6139       /* The symbol is probably not bound yet, so find the real one */
6140       csym = findSymWithLevel (SymbolTab, func);
6141       if (csym)
6142         func = csym;
6143
6144       /* Is this an inline function that we can inline? */
6145       if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6146         {
6147           symbol * retsym = NULL;
6148           symbol * retlab;
6149           ast * inlinetree;
6150           ast * inlinetree2;
6151           ast * temptree;
6152           value * args;
6153           int argIndex;
6154
6155           /* Generate a label for the inlined function to branch to */
6156           /* in case it contains a return statement */
6157           retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6158           retlab->isitmp = 1;
6159           retlab->islbl = 1;
6160           inlineState.retlab = retlab;
6161
6162           /* Build the subtree for the inlined function in the form: */
6163           /* { //inlinetree block                                    */
6164           /*   { //inlinetree2 block                                 */
6165           /*     inline_function_code;                               */
6166           /*     retlab:                                             */
6167           /*   }                                                     */
6168           /* }                                                       */
6169           temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6170           copyAstLoc (temptree, tree);
6171           temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6172           copyAstLoc (temptree, tree);
6173           temptree = newNode (BLOCK, NULL, temptree);
6174           copyAstLoc (temptree, tree);
6175           inlinetree2 = temptree;
6176           inlinetree = newNode (BLOCK, NULL, inlinetree2);
6177           copyAstLoc (inlinetree, tree);
6178
6179           /* To pass parameters to the inlined function, we need some  */
6180           /* intermediate variables. This avoids scoping problems      */
6181           /* when the parameter declaration names are used differently */
6182           /* during the function call. For example, a function         */
6183           /* declared as func(int x, int y) but called as func(y,x).   */
6184           /* { //inlinetree block                                      */
6185           /*   type1 temparg1;                                         */
6186           /*   ...                                                     */
6187           /*   typen tempargn;                                         */
6188           /*   temparg1 = argument1;                                   */
6189           /*   ...                                                     */
6190           /*   tempargn = argumentn;                                   */
6191           /*   { //inlinetree2 block                                   */
6192           /*     type1 param1;                                         */
6193           /*     ...                                                   */
6194           /*     typen paramn;                                         */
6195           /*     param1 = temparg1;                                    */
6196           /*     ...                                                   */
6197           /*     paramn = tempargn;                                    */
6198           /*     inline_function_code;                                 */
6199           /*     retlab:                                               */
6200           /*   }                                                       */
6201           /* }                                                         */
6202           args = FUNC_ARGS (func->type);
6203           argIndex = 0;
6204           while (args)
6205             {
6206               symbol * temparg;
6207               ast * passedarg;
6208               ast * assigntree;
6209               symbol * parm = copySymbol (args->sym);
6210
6211               temparg = inlineTempVar (args->sym->type, tree->level+1);
6212               inlineAddDecl (temparg, inlinetree, FALSE);
6213
6214               passedarg = inlineFindParm (tree->right, argIndex);
6215               assigntree = newNode ('=',
6216                                     newAst_VALUE (symbolVal (temparg)),
6217                                     passedarg);
6218               inlinetree->right = newNode (NULLOP,
6219                                            assigntree,
6220                                            inlinetree->right);
6221
6222               inlineAddDecl (parm, inlinetree2, FALSE);
6223               parm->_isparm = 0;
6224
6225               assigntree = newNode ('=',
6226                                     newAst_VALUE (symbolVal (parm)),
6227                                     newAst_VALUE (symbolVal (temparg)));
6228               inlinetree2->right = newNode (NULLOP,
6229                                            assigntree,
6230                                            inlinetree2->right);
6231
6232
6233               args = args->next;
6234               argIndex++;
6235             }
6236
6237           /* Handle the return type */
6238           if (!IS_VOID (func->type->next))
6239             {
6240               /* Create a temporary symbol to hold the return value and   */
6241               /* join it with the inlined function using the comma        */
6242               /* operator. The fixupInline function will take care of     */
6243               /* changing return statements into assignments to retsym.   */
6244               /* (parameter passing and return label omitted for clarity) */
6245               /* rettype retsym;                                          */
6246               /* ...                                                      */
6247               /* {{inline_function_code}}, retsym                         */
6248
6249               retsym = inlineTempVar (func->type->next, tree->level);
6250               inlineAddDecl (retsym, block, TRUE);
6251
6252               tree->opval.op = ',';
6253               tree->left = inlinetree;
6254               tree->right = newAst_VALUE (symbolVal (retsym));
6255             }
6256           else
6257             {
6258               tree->opval.op = NULLOP;
6259               tree->left = NULL;
6260               tree->right = inlinetree;
6261             }
6262           inlineState.retsym = retsym;
6263
6264           /* Renumber the various internal counters on the inlined   */
6265           /* function's tree nodes and symbols. Add the inlined      */
6266           /* function's local variables to the appropriate scope(s). */
6267           /* Convert inlined return statements to an assignment to   */
6268           /* retsym (if needed) and a goto retlab.                   */
6269           fixupInline (inlinetree, inlinetree->level);
6270           inlineState.count++;
6271         }
6272
6273     }
6274
6275   /* Recursively continue to search for functions to inline. */
6276   if (IS_AST_OP (tree))
6277     {
6278       if (tree->opval.op == BLOCK)
6279         block = tree;
6280
6281       if (tree->left)
6282         expandInlineFuncs (tree->left, block);
6283       if (tree->right)
6284         expandInlineFuncs (tree->right, block);
6285     }
6286 }
6287
6288
6289 /*-----------------------------------------------------------------*/
6290 /* createFunction - This is the key node that calls the iCode for  */
6291 /*                  generating the code for a function. Note code  */
6292 /*                  is generated function by function, later when  */
6293 /*                  add inter-procedural analysis this will change */
6294 /*-----------------------------------------------------------------*/
6295 ast *
6296 createFunction (symbol * name, ast * body)
6297 {
6298   ast *ex;
6299   symbol *csym;
6300   int stack = 0;
6301   sym_link *fetype;
6302   iCode *piCode = NULL;
6303
6304   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6305     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6306
6307   /* if check function return 0 then some problem */
6308   if (checkFunction (name, NULL) == 0)
6309     return NULL;
6310
6311   /* create a dummy block if none exists */
6312   if (!body)
6313     body = newNode (BLOCK, NULL, NULL);
6314
6315   noLineno++;
6316
6317   /* check if the function name already in the symbol table */
6318   if ((csym = findSym (SymbolTab, NULL, name->name)))
6319     {
6320       name = csym;
6321       /* special case for compiler defined functions
6322          we need to add the name to the publics list : this
6323          actually means we are now compiling the compiler
6324          support routine */
6325       if (name->cdef)
6326         {
6327           addSet (&publics, name);
6328         }
6329     }
6330   else
6331     {
6332       addSymChain (&name);
6333       allocVariables (name);
6334     }
6335   name->lastLine = lexLineno;
6336   currFunc = name;
6337
6338   /* set the stack pointer */
6339   stackPtr  = -port->stack.direction * port->stack.call_overhead;
6340   xstackPtr = 0;
6341
6342   if (IFFUNC_ISISR (name->type))
6343     stackPtr -= port->stack.direction * port->stack.isr_overhead;
6344
6345   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6346     {
6347       if (options.useXstack)
6348         xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6349       else
6350         stackPtr  -= port->stack.direction * port->stack.reent_overhead;
6351     }
6352
6353   fetype = getSpec (name->type);        /* get the specifier for the function */
6354   /* if this is a reentrant function then */
6355   if (IFFUNC_ISREENT (name->type))
6356     reentrant++;
6357
6358   inlineState.count = 0;
6359   expandInlineFuncs (body, NULL);
6360
6361   if (FUNC_ISINLINE (name->type))
6362     name->funcTree = copyAst (body);
6363
6364   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
6365
6366   /* do processing for parameters that are passed in registers */
6367   processRegParms (FUNC_ARGS(name->type), body);
6368
6369   /* set the stack pointer */
6370   stackPtr = 0;
6371   xstackPtr = -1;
6372
6373   gatherImplicitVariables (body, NULL);  /* move implicit variables into blocks */
6374
6375   /* allocate & autoinit the block variables */
6376   processBlockVars (body, &stack, ALLOCATE);
6377
6378   /* name needs to be mangled */
6379   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6380
6381   body = resolveSymbols (body); /* resolve the symbols */
6382   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6383
6384   /* save the stack information */
6385   if (options.useXstack)
6386     name->xstack = SPEC_STAK (fetype) = stack;
6387   else
6388     name->stack = SPEC_STAK (fetype) = stack;
6389
6390   ex = newAst_VALUE (symbolVal (name)); /* create name */
6391   ex = newNode (FUNCTION, ex, body);
6392   ex->values.args = FUNC_ARGS(name->type);
6393   ex->decorated=1;
6394   if (options.dump_tree)
6395     PA(ex);
6396   if (fatalError)
6397     goto skipall;
6398
6399   /* Do not generate code for inline functions unless extern also. */
6400 #if 0
6401   if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6402     goto skipall;
6403 #else
6404   /* Temporary hack: always generate code for static inline functions. */
6405   /* Ideally static inline functions should only be generated if needed. */
6406   if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6407     goto skipall;
6408 #endif
6409
6410   /* create the node & generate intermediate code */
6411   GcurMemmap = code;
6412   codeOutBuf = &code->oBuf;
6413   piCode = iCodeFromAst (ex);
6414   name->generated = 1;
6415
6416   if (fatalError)
6417     goto skipall;
6418
6419   eBBlockFromiCode (piCode);
6420
6421   /* if there are any statics then do them */
6422   if (staticAutos)
6423     {
6424       GcurMemmap = statsg;
6425       codeOutBuf = &statsg->oBuf;
6426       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6427       staticAutos = NULL;
6428     }
6429
6430 skipall:
6431
6432   /* dealloc the block variables */
6433   processBlockVars (body, &stack, DEALLOCATE);
6434   outputDebugStackSymbols();
6435   /* deallocate paramaters */
6436   deallocParms (FUNC_ARGS(name->type));
6437
6438   if (IFFUNC_ISREENT (name->type))
6439     reentrant--;
6440
6441   /* we are done freeup memory & cleanup */
6442   noLineno--;
6443   if (port->reset_labelKey) labelKey = 1;
6444   name->key = 0;
6445   FUNC_HASBODY(name->type) = 1;
6446   addSet (&operKeyReset, name);
6447   applyToSet (operKeyReset, resetParmKey);
6448
6449   if (options.debug)
6450     cdbStructBlock(1);
6451
6452   cleanUpLevel (LabelTab, 0);
6453   cleanUpBlock (StructTab, 1);
6454   cleanUpBlock (TypedefTab, 1);
6455
6456   xstack->syms = NULL;
6457   istack->syms = NULL;
6458   return NULL;
6459 }
6460
6461
6462 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6463 /*-----------------------------------------------------------------*/
6464 /* ast_print : prints the ast (for debugging purposes)             */
6465 /*-----------------------------------------------------------------*/
6466
6467 void ast_print (ast * tree, FILE *outfile, int indent)
6468 {
6469
6470   if (!tree) return ;
6471
6472   /* can print only decorated trees */
6473   if (!tree->decorated) return;
6474
6475   /* if any child is an error | this one is an error do nothing */
6476   if (tree->isError ||
6477     (tree->left && tree->left->isError) ||
6478     (tree->right && tree->right->isError)) {
6479     fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6480   }
6481
6482
6483   /* print the line          */
6484   /* if not block & function */
6485   if (tree->type == EX_OP &&
6486     (tree->opval.op != FUNCTION &&
6487     tree->opval.op != BLOCK &&
6488     tree->opval.op != NULLOP)) {
6489   }
6490
6491   if (tree->opval.op == FUNCTION) {
6492     int arg=0;
6493     value *args=FUNC_ARGS(tree->left->opval.val->type);
6494     fprintf(outfile,"FUNCTION (%s=%p) type (",
6495       tree->left->opval.val->name, tree);
6496     printTypeChain (tree->left->opval.val->type->next,outfile);
6497     fprintf(outfile,") args (");
6498     do {
6499       if (arg) {
6500         fprintf (outfile, ", ");
6501       }
6502       printTypeChain (args ? args->type : NULL, outfile);
6503       arg++;
6504       args= args ? args->next : NULL;
6505     } while (args);
6506     fprintf(outfile,")\n");
6507     ast_print(tree->left,outfile,indent);
6508     ast_print(tree->right,outfile,indent);
6509     return ;
6510   }
6511   if (tree->opval.op == BLOCK) {
6512     symbol *decls = tree->values.sym;
6513     INDENT(indent,outfile);
6514     fprintf(outfile,"{\n");
6515     while (decls) {
6516       INDENT(indent+2,outfile);
6517       fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6518         decls->name, decls);
6519       printTypeChain(decls->type,outfile);
6520       fprintf(outfile,")\n");
6521
6522       decls = decls->next;
6523     }
6524     ast_print(tree->right,outfile,indent+2);
6525     INDENT(indent,outfile);
6526     fprintf(outfile,"}\n");
6527     return;
6528   }
6529   if (tree->opval.op == NULLOP) {
6530     ast_print(tree->left,outfile,indent);
6531     ast_print(tree->right,outfile,indent);
6532     return ;
6533   }
6534   INDENT(indent,outfile);
6535
6536   /*------------------------------------------------------------------*/
6537   /*----------------------------*/
6538   /*   leaf has been reached    */
6539   /*----------------------------*/
6540   /* if this is of type value */
6541   /* just get the type        */
6542   if (tree->type == EX_VALUE) {
6543
6544     if (IS_LITERAL (tree->opval.val->etype)) {
6545       fprintf(outfile,"CONSTANT (%p) value = ", tree);
6546       if (SPEC_USIGN (tree->opval.val->etype))
6547         fprintf(outfile,"%u", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val));
6548       else
6549         fprintf(outfile,"%d", (TYPE_TARGET_LONG) floatFromVal(tree->opval.val));
6550       fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val),
6551         floatFromVal(tree->opval.val));
6552     } else if (tree->opval.val->sym) {
6553       /* if the undefined flag is set then give error message */
6554       if (tree->opval.val->sym->undefined) {
6555         fprintf(outfile,"UNDEFINED SYMBOL ");
6556       } else {
6557         fprintf(outfile,"SYMBOL ");
6558       }
6559       fprintf(outfile,"(%s=%p @ %p)",
6560         tree->opval.val->sym->name, tree, tree->opval.val->sym);
6561     }
6562     if (tree->ftype) {
6563       fprintf(outfile," type (");
6564       printTypeChain(tree->ftype,outfile);
6565       fprintf(outfile,")\n");
6566     } else {
6567       fprintf(outfile,"\n");
6568     }
6569     return ;
6570   }
6571
6572   /* if type link for the case of cast */
6573   if (tree->type == EX_LINK) {
6574     fprintf(outfile,"TYPENODE (%p) type = (",tree);
6575     printTypeChain(tree->opval.lnk,outfile);
6576     fprintf(outfile,")\n");
6577     return ;
6578   }
6579
6580
6581   /* depending on type of operator do */
6582
6583   switch (tree->opval.op) {
6584     /*------------------------------------------------------------------*/
6585     /*----------------------------*/
6586     /*        array node          */
6587     /*----------------------------*/
6588   case '[':
6589     fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6590     printTypeChain(tree->ftype,outfile);
6591     fprintf(outfile,")\n");
6592     ast_print(tree->left,outfile,indent+2);
6593     ast_print(tree->right,outfile,indent+2);
6594     return;
6595
6596     /*------------------------------------------------------------------*/
6597     /*----------------------------*/
6598     /*      struct/union          */
6599     /*----------------------------*/
6600   case '.':
6601     fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6602     printTypeChain(tree->ftype,outfile);
6603     fprintf(outfile,")\n");
6604     ast_print(tree->left,outfile,indent+2);
6605     ast_print(tree->right,outfile,indent+2);
6606     return ;
6607
6608     /*------------------------------------------------------------------*/
6609     /*----------------------------*/
6610     /*    struct/union pointer    */
6611     /*----------------------------*/
6612   case PTR_OP:
6613     fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6614     printTypeChain(tree->ftype,outfile);
6615     fprintf(outfile,")\n");
6616     ast_print(tree->left,outfile,indent+2);
6617     ast_print(tree->right,outfile,indent+2);
6618     return ;
6619
6620     /*------------------------------------------------------------------*/
6621     /*----------------------------*/
6622     /*  ++/-- operation           */
6623     /*----------------------------*/
6624   case INC_OP:
6625     if (tree->left)
6626       fprintf(outfile,"post-");
6627     else
6628       fprintf(outfile,"pre-");
6629     fprintf(outfile,"INC_OP (%p) type (",tree);
6630     printTypeChain(tree->ftype,outfile);
6631     fprintf(outfile,")\n");
6632     ast_print(tree->left,outfile,indent+2); /* postincrement case */
6633     ast_print(tree->right,outfile,indent+2); /* preincrement case */
6634     return ;
6635
6636   case DEC_OP:
6637     if (tree->left)
6638       fprintf(outfile,"post-");
6639     else
6640       fprintf(outfile,"pre-");
6641     fprintf(outfile,"DEC_OP (%p) type (",tree);
6642     printTypeChain(tree->ftype,outfile);
6643     fprintf(outfile,")\n");
6644     ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6645     ast_print(tree->right,outfile,indent+2); /* predecrement case */
6646     return ;
6647
6648     /*------------------------------------------------------------------*/
6649     /*----------------------------*/
6650     /*  bitwise and               */
6651     /*----------------------------*/
6652   case '&':
6653     if (tree->right) {
6654       fprintf(outfile,"& (%p) type (",tree);
6655       printTypeChain(tree->ftype,outfile);
6656       fprintf(outfile,")\n");
6657       ast_print(tree->left,outfile,indent+2);
6658       ast_print(tree->right,outfile,indent+2);
6659     } else {
6660       fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6661       printTypeChain(tree->ftype,outfile);
6662       fprintf(outfile,")\n");
6663       ast_print(tree->left,outfile,indent+2);
6664       ast_print(tree->right,outfile,indent+2);
6665     }
6666     return ;
6667     /*----------------------------*/
6668     /*  bitwise or                */
6669     /*----------------------------*/
6670   case '|':
6671     fprintf(outfile,"OR (%p) type (",tree);
6672     printTypeChain(tree->ftype,outfile);
6673     fprintf(outfile,")\n");
6674     ast_print(tree->left,outfile,indent+2);
6675     ast_print(tree->right,outfile,indent+2);
6676     return ;
6677     /*------------------------------------------------------------------*/
6678     /*----------------------------*/
6679     /*  bitwise xor               */
6680     /*----------------------------*/
6681   case '^':
6682     fprintf(outfile,"XOR (%p) type (",tree);
6683     printTypeChain(tree->ftype,outfile);
6684     fprintf(outfile,")\n");
6685     ast_print(tree->left,outfile,indent+2);
6686     ast_print(tree->right,outfile,indent+2);
6687     return ;
6688
6689     /*------------------------------------------------------------------*/
6690     /*----------------------------*/
6691     /*  division                  */
6692     /*----------------------------*/
6693   case '/':
6694     fprintf(outfile,"DIV (%p) type (",tree);
6695     printTypeChain(tree->ftype,outfile);
6696     fprintf(outfile,")\n");
6697     ast_print(tree->left,outfile,indent+2);
6698     ast_print(tree->right,outfile,indent+2);
6699     return ;
6700     /*------------------------------------------------------------------*/
6701     /*----------------------------*/
6702     /*            modulus         */
6703     /*----------------------------*/
6704   case '%':
6705     fprintf(outfile,"MOD (%p) type (",tree);
6706     printTypeChain(tree->ftype,outfile);
6707     fprintf(outfile,")\n");
6708     ast_print(tree->left,outfile,indent+2);
6709     ast_print(tree->right,outfile,indent+2);
6710     return ;
6711
6712     /*------------------------------------------------------------------*/
6713     /*----------------------------*/
6714     /*  address dereference       */
6715     /*----------------------------*/
6716   case '*':                       /* can be unary  : if right is null then unary operation */
6717     if (!tree->right) {
6718       fprintf(outfile,"DEREF (%p) type (",tree);
6719       printTypeChain(tree->ftype,outfile);
6720       fprintf(outfile,")\n");
6721       ast_print(tree->left,outfile,indent+2);
6722       return ;
6723     }
6724     /*------------------------------------------------------------------*/
6725     /*----------------------------*/
6726     /*      multiplication        */
6727     /*----------------------------*/
6728     fprintf(outfile,"MULT (%p) type (",tree);
6729     printTypeChain(tree->ftype,outfile);
6730     fprintf(outfile,")\n");
6731     ast_print(tree->left,outfile,indent+2);
6732     ast_print(tree->right,outfile,indent+2);
6733     return ;
6734
6735
6736     /*------------------------------------------------------------------*/
6737     /*----------------------------*/
6738     /*    unary '+' operator      */
6739     /*----------------------------*/
6740   case '+':
6741     /* if unary plus */
6742     if (!tree->right) {
6743       fprintf(outfile,"UPLUS (%p) type (",tree);
6744       printTypeChain(tree->ftype,outfile);
6745       fprintf(outfile,")\n");
6746       ast_print(tree->left,outfile,indent+2);
6747     } else {
6748       /*------------------------------------------------------------------*/
6749       /*----------------------------*/
6750       /*      addition              */
6751       /*----------------------------*/
6752       fprintf(outfile,"ADD (%p) type (",tree);
6753       printTypeChain(tree->ftype,outfile);
6754       fprintf(outfile,")\n");
6755       ast_print(tree->left,outfile,indent+2);
6756       ast_print(tree->right,outfile,indent+2);
6757     }
6758     return;
6759     /*------------------------------------------------------------------*/
6760     /*----------------------------*/
6761     /*      unary '-'             */
6762     /*----------------------------*/
6763   case '-':                       /* can be unary   */
6764     if (!tree->right) {
6765       fprintf(outfile,"UMINUS (%p) type (",tree);
6766       printTypeChain(tree->ftype,outfile);
6767       fprintf(outfile,")\n");
6768       ast_print(tree->left,outfile,indent+2);
6769     } else {
6770       /*------------------------------------------------------------------*/
6771       /*----------------------------*/
6772       /*      subtraction           */
6773       /*----------------------------*/
6774       fprintf(outfile,"SUB (%p) type (",tree);
6775       printTypeChain(tree->ftype,outfile);
6776       fprintf(outfile,")\n");
6777       ast_print(tree->left,outfile,indent+2);
6778       ast_print(tree->right,outfile,indent+2);
6779     }
6780     return;
6781     /*------------------------------------------------------------------*/
6782     /*----------------------------*/
6783     /*    complement              */
6784     /*----------------------------*/
6785   case '~':
6786     fprintf(outfile,"COMPL (%p) type (",tree);
6787     printTypeChain(tree->ftype,outfile);
6788     fprintf(outfile,")\n");
6789     ast_print(tree->left,outfile,indent+2);
6790     return ;
6791     /*------------------------------------------------------------------*/
6792     /*----------------------------*/
6793     /*           not              */
6794     /*----------------------------*/
6795   case '!':
6796     fprintf(outfile,"NOT (%p) type (",tree);
6797     printTypeChain(tree->ftype,outfile);
6798     fprintf(outfile,")\n");
6799     ast_print(tree->left,outfile,indent+2);
6800     return ;
6801     /*------------------------------------------------------------------*/
6802     /*----------------------------*/
6803     /*           shift            */
6804     /*----------------------------*/
6805   case RRC:
6806     fprintf(outfile,"RRC (%p) type (",tree);
6807     printTypeChain(tree->ftype,outfile);
6808     fprintf(outfile,")\n");
6809     ast_print(tree->left,outfile,indent+2);
6810     return ;
6811
6812   case RLC:
6813     fprintf(outfile,"RLC (%p) type (",tree);
6814     printTypeChain(tree->ftype,outfile);
6815     fprintf(outfile,")\n");
6816     ast_print(tree->left,outfile,indent+2);
6817     return ;
6818   case SWAP:
6819     fprintf(outfile,"SWAP (%p) type (",tree);
6820     printTypeChain(tree->ftype,outfile);
6821     fprintf(outfile,")\n");
6822     ast_print(tree->left,outfile,indent+2);
6823     return ;
6824   case GETHBIT:
6825     fprintf(outfile,"GETHBIT (%p) type (",tree);
6826     printTypeChain(tree->ftype,outfile);
6827     fprintf(outfile,")\n");
6828     ast_print(tree->left,outfile,indent+2);
6829     return ;
6830   case GETABIT:
6831     fprintf(outfile,"GETABIT (%p) type (",tree);
6832     printTypeChain(tree->ftype,outfile);
6833     fprintf(outfile,")\n");
6834     ast_print(tree->left,outfile,indent+2);
6835     ast_print(tree->right,outfile,indent+2);
6836     return ;
6837   case GETBYTE:
6838     fprintf(outfile,"GETBYTE (%p) type (",tree);
6839     printTypeChain(tree->ftype,outfile);
6840     fprintf(outfile,")\n");
6841     ast_print(tree->left,outfile,indent+2);
6842     ast_print(tree->right,outfile,indent+2);
6843     return ;
6844   case GETWORD:
6845     fprintf(outfile,"GETWORD (%p) type (",tree);
6846     printTypeChain(tree->ftype,outfile);
6847     fprintf(outfile,")\n");
6848     ast_print(tree->left,outfile,indent+2);
6849     ast_print(tree->right,outfile,indent+2);
6850     return ;
6851   case LEFT_OP:
6852     fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6853     printTypeChain(tree->ftype,outfile);
6854     fprintf(outfile,")\n");
6855     ast_print(tree->left,outfile,indent+2);
6856     ast_print(tree->right,outfile,indent+2);
6857     return ;
6858   case RIGHT_OP:
6859     fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6860     printTypeChain(tree->ftype,outfile);
6861     fprintf(outfile,")\n");
6862     ast_print(tree->left,outfile,indent+2);
6863     ast_print(tree->right,outfile,indent+2);
6864     return ;
6865     /*------------------------------------------------------------------*/
6866     /*----------------------------*/
6867     /*         casting            */
6868     /*----------------------------*/
6869   case CAST:                      /* change the type   */
6870     fprintf(outfile,"CAST (%p) from type (",tree);
6871     printTypeChain(tree->right->ftype,outfile);
6872     fprintf(outfile,") to type (");
6873     printTypeChain(tree->ftype,outfile);
6874     fprintf(outfile,")\n");
6875     ast_print(tree->right,outfile,indent+2);
6876     return ;
6877
6878   case AND_OP:
6879     fprintf(outfile,"ANDAND (%p) type (",tree);
6880     printTypeChain(tree->ftype,outfile);
6881     fprintf(outfile,")\n");
6882     ast_print(tree->left,outfile,indent+2);
6883     ast_print(tree->right,outfile,indent+2);
6884     return ;
6885   case OR_OP:
6886     fprintf(outfile,"OROR (%p) type (",tree);
6887     printTypeChain(tree->ftype,outfile);
6888     fprintf(outfile,")\n");
6889     ast_print(tree->left,outfile,indent+2);
6890     ast_print(tree->right,outfile,indent+2);
6891     return ;
6892
6893     /*------------------------------------------------------------------*/
6894     /*----------------------------*/
6895     /*     comparison operators   */
6896     /*----------------------------*/
6897   case '>':
6898     fprintf(outfile,"GT(>) (%p) type (",tree);
6899     printTypeChain(tree->ftype,outfile);
6900     fprintf(outfile,")\n");
6901     ast_print(tree->left,outfile,indent+2);
6902     ast_print(tree->right,outfile,indent+2);
6903     return ;
6904   case '<':
6905     fprintf(outfile,"LT(<) (%p) type (",tree);
6906     printTypeChain(tree->ftype,outfile);
6907     fprintf(outfile,")\n");
6908     ast_print(tree->left,outfile,indent+2);
6909     ast_print(tree->right,outfile,indent+2);
6910     return ;
6911   case LE_OP:
6912     fprintf(outfile,"LE(<=) (%p) type (",tree);
6913     printTypeChain(tree->ftype,outfile);
6914     fprintf(outfile,")\n");
6915     ast_print(tree->left,outfile,indent+2);
6916     ast_print(tree->right,outfile,indent+2);
6917     return ;
6918   case GE_OP:
6919     fprintf(outfile,"GE(>=) (%p) type (",tree);
6920     printTypeChain(tree->ftype,outfile);
6921     fprintf(outfile,")\n");
6922     ast_print(tree->left,outfile,indent+2);
6923     ast_print(tree->right,outfile,indent+2);
6924     return ;
6925   case EQ_OP:
6926     fprintf(outfile,"EQ(==) (%p) type (",tree);
6927     printTypeChain(tree->ftype,outfile);
6928     fprintf(outfile,")\n");
6929     ast_print(tree->left,outfile,indent+2);
6930     ast_print(tree->right,outfile,indent+2);
6931     return ;
6932   case NE_OP:
6933     fprintf(outfile,"NE(!=) (%p) type (",tree);
6934     printTypeChain(tree->ftype,outfile);
6935     fprintf(outfile,")\n");
6936     ast_print(tree->left,outfile,indent+2);
6937     ast_print(tree->right,outfile,indent+2);
6938     /*------------------------------------------------------------------*/
6939     /*----------------------------*/
6940     /*             sizeof         */
6941     /*----------------------------*/
6942   case SIZEOF:            /* evaluate wihout code generation */
6943     fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
6944     return ;
6945
6946     /*------------------------------------------------------------------*/
6947     /*----------------------------*/
6948     /* conditional operator  '?'  */
6949     /*----------------------------*/
6950   case '?':
6951     fprintf(outfile,"QUEST(?) (%p) type (",tree);
6952     printTypeChain(tree->ftype,outfile);
6953     fprintf(outfile,")\n");
6954     ast_print(tree->left,outfile,indent+2);
6955     ast_print(tree->right,outfile,indent+2);
6956     return;
6957
6958   case ':':
6959     fprintf(outfile,"COLON(:) (%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     /*------------------------------------------------------------------*/
6967     /*----------------------------*/
6968     /*    assignment operators    */
6969     /*----------------------------*/
6970   case MUL_ASSIGN:
6971     fprintf(outfile,"MULASS(*=) (%p) type (",tree);
6972     printTypeChain(tree->ftype,outfile);
6973     fprintf(outfile,")\n");
6974     ast_print(tree->left,outfile,indent+2);
6975     ast_print(tree->right,outfile,indent+2);
6976     return;
6977   case DIV_ASSIGN:
6978     fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
6979     printTypeChain(tree->ftype,outfile);
6980     fprintf(outfile,")\n");
6981     ast_print(tree->left,outfile,indent+2);
6982     ast_print(tree->right,outfile,indent+2);
6983     return;
6984   case AND_ASSIGN:
6985     fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
6986     printTypeChain(tree->ftype,outfile);
6987     fprintf(outfile,")\n");
6988     ast_print(tree->left,outfile,indent+2);
6989     ast_print(tree->right,outfile,indent+2);
6990     return;
6991   case OR_ASSIGN:
6992     fprintf(outfile,"ORASS(|=) (%p) type (",tree);
6993     printTypeChain(tree->ftype,outfile);
6994     fprintf(outfile,")\n");
6995     ast_print(tree->left,outfile,indent+2);
6996     ast_print(tree->right,outfile,indent+2);
6997     return;
6998   case XOR_ASSIGN:
6999     fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7000     printTypeChain(tree->ftype,outfile);
7001     fprintf(outfile,")\n");
7002     ast_print(tree->left,outfile,indent+2);
7003     ast_print(tree->right,outfile,indent+2);
7004     return;
7005   case RIGHT_ASSIGN:
7006     fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7007     printTypeChain(tree->ftype,outfile);
7008     fprintf(outfile,")\n");
7009     ast_print(tree->left,outfile,indent+2);
7010     ast_print(tree->right,outfile,indent+2);
7011     return;
7012   case LEFT_ASSIGN:
7013     fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7014     printTypeChain(tree->ftype,outfile);
7015     fprintf(outfile,")\n");
7016     ast_print(tree->left,outfile,indent+2);
7017     ast_print(tree->right,outfile,indent+2);
7018     return;
7019     /*------------------------------------------------------------------*/
7020     /*----------------------------*/
7021     /*    -= operator             */
7022     /*----------------------------*/
7023   case SUB_ASSIGN:
7024     fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7025     printTypeChain(tree->ftype,outfile);
7026     fprintf(outfile,")\n");
7027     ast_print(tree->left,outfile,indent+2);
7028     ast_print(tree->right,outfile,indent+2);
7029     return;
7030     /*------------------------------------------------------------------*/
7031     /*----------------------------*/
7032     /*          += operator       */
7033     /*----------------------------*/
7034   case ADD_ASSIGN:
7035     fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7036     printTypeChain(tree->ftype,outfile);
7037     fprintf(outfile,")\n");
7038     ast_print(tree->left,outfile,indent+2);
7039     ast_print(tree->right,outfile,indent+2);
7040     return;
7041     /*------------------------------------------------------------------*/
7042     /*----------------------------*/
7043     /*      straight assignemnt   */
7044     /*----------------------------*/
7045   case '=':
7046     fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7047     printTypeChain(tree->ftype,outfile);
7048     fprintf(outfile,")\n");
7049     ast_print(tree->left,outfile,indent+2);
7050     ast_print(tree->right,outfile,indent+2);
7051     return;
7052     /*------------------------------------------------------------------*/
7053     /*----------------------------*/
7054     /*      comma operator        */
7055     /*----------------------------*/
7056   case ',':
7057     fprintf(outfile,"COMMA(,) (%p) type (",tree);
7058     printTypeChain(tree->ftype,outfile);
7059     fprintf(outfile,")\n");
7060     ast_print(tree->left,outfile,indent+2);
7061     ast_print(tree->right,outfile,indent+2);
7062     return;
7063     /*------------------------------------------------------------------*/
7064     /*----------------------------*/
7065     /*       function call        */
7066     /*----------------------------*/
7067   case CALL:
7068   case PCALL:
7069     fprintf(outfile,"CALL (%p) type (",tree);
7070     printTypeChain(tree->ftype,outfile);
7071     fprintf(outfile,")\n");
7072     ast_print(tree->left,outfile,indent+2);
7073     ast_print(tree->right,outfile,indent+2);
7074     return;
7075   case PARAM:
7076     fprintf(outfile,"PARMS\n");
7077     ast_print(tree->left,outfile,indent+2);
7078     if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7079       ast_print(tree->right,outfile,indent+2);
7080     }
7081     return ;
7082     /*------------------------------------------------------------------*/
7083     /*----------------------------*/
7084     /*     return statement       */
7085     /*----------------------------*/
7086   case RETURN:
7087     fprintf(outfile,"RETURN (%p) type (",tree);
7088     if (tree->right) {
7089       printTypeChain(tree->right->ftype,outfile);
7090     }
7091     fprintf(outfile,")\n");
7092     ast_print(tree->right,outfile,indent+2);
7093     return ;
7094     /*------------------------------------------------------------------*/
7095     /*----------------------------*/
7096     /*     label statement        */
7097     /*----------------------------*/
7098   case LABEL :
7099     fprintf(outfile,"LABEL (%p)\n",tree);
7100     ast_print(tree->left,outfile,indent+2);
7101     ast_print(tree->right,outfile,indent);
7102     return;
7103     /*------------------------------------------------------------------*/
7104     /*----------------------------*/
7105     /*     switch statement       */
7106     /*----------------------------*/
7107   case SWITCH:
7108     {
7109       value *val;
7110       fprintf(outfile,"SWITCH (%p) ",tree);
7111       ast_print(tree->left,outfile,0);
7112       for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7113         INDENT(indent+2,outfile);
7114         fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7115           (int) floatFromVal(val),
7116           tree->values.switchVals.swNum,
7117           (int) floatFromVal(val));
7118       }
7119       ast_print(tree->right,outfile,indent);
7120     }
7121     return ;
7122     /*------------------------------------------------------------------*/
7123     /*----------------------------*/
7124     /* ifx Statement              */
7125     /*----------------------------*/
7126   case IFX:
7127     fprintf(outfile,"IF (%p) \n",tree);
7128     ast_print(tree->left,outfile,indent+2);
7129     if (tree->trueLabel) {
7130       INDENT(indent+2,outfile);
7131       fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7132     }
7133     if (tree->falseLabel) {
7134       INDENT(indent+2,outfile);
7135       fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7136     }
7137     ast_print(tree->right,outfile,indent+2);
7138     return ;
7139     /*----------------------------*/
7140     /* goto Statement              */
7141     /*----------------------------*/
7142   case GOTO:
7143     fprintf(outfile,"GOTO (%p) \n",tree);
7144     ast_print(tree->left,outfile,indent+2);
7145     fprintf(outfile,"\n");
7146     return ;
7147     /*------------------------------------------------------------------*/
7148     /*----------------------------*/
7149     /* for Statement              */
7150     /*----------------------------*/
7151   case FOR:
7152     fprintf(outfile,"FOR (%p) \n",tree);
7153     if (AST_FOR( tree, initExpr)) {
7154       INDENT(indent+2,outfile);
7155       fprintf(outfile,"INIT EXPR ");
7156       ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7157     }
7158     if (AST_FOR( tree, condExpr)) {
7159       INDENT(indent+2,outfile);
7160       fprintf(outfile,"COND EXPR ");
7161       ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7162     }
7163     if (AST_FOR( tree, loopExpr)) {
7164       INDENT(indent+2,outfile);
7165       fprintf(outfile,"LOOP EXPR ");
7166       ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7167     }
7168     fprintf(outfile,"FOR LOOP BODY \n");
7169     ast_print(tree->left,outfile,indent+2);
7170     return ;
7171   case CRITICAL:
7172     fprintf(outfile,"CRITICAL (%p) \n",tree);
7173     ast_print(tree->left,outfile,indent+2);
7174   default:
7175     return ;
7176   }
7177 }
7178
7179 void PA(ast *t)
7180 {
7181   ast_print(t,stdout,0);
7182 }
7183
7184 /*-----------------------------------------------------------------*/
7185 /* astErrors : returns non-zero if errors present in tree          */
7186 /*-----------------------------------------------------------------*/
7187 int astErrors(ast *t)
7188 {
7189   int errors=0;
7190
7191   if (t)
7192     {
7193       if (t->isError)
7194         errors++;
7195
7196       if (t->type == EX_VALUE
7197           && t->opval.val->sym
7198           && t->opval.val->sym->undefined)
7199         errors++;
7200
7201       errors += astErrors(t->left);
7202       errors += astErrors(t->right);
7203     }
7204
7205   return errors;
7206 }