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