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