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