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