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