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