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