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