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