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