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