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