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