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