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