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