* device/include/pic16/pic18fregs.h,
[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         return resultType;
2284       case '=':
2285       case '?':
2286       case ':':
2287       case '|':
2288       case '^':
2289       case '~':
2290       case '*':
2291       case '+':
2292       case '-':
2293       case LABEL:
2294         return resultType;
2295       case '&':
2296         if (!tree->right)
2297           /* can be unary */
2298           return RESULT_TYPE_NONE;
2299         else
2300           return resultType;
2301       case IFX:
2302         return RESULT_TYPE_IFX;
2303       default:
2304         return RESULT_TYPE_NONE;
2305     }
2306 }
2307
2308 /*-----------------------------------------------------------------*/
2309 /* getLeftResultType - gets type from left branch for propagation  */
2310 /*-----------------------------------------------------------------*/
2311 static RESULT_TYPE
2312 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2313 {
2314   switch (tree->opval.op)
2315     {
2316       case '=':
2317       case CAST:
2318         if (IS_PTR (LTYPE (tree)))
2319           return RESULT_TYPE_NONE;
2320         else
2321           return getResultTypeFromType (LETYPE (tree));
2322       case RETURN:
2323         if (IS_PTR (currFunc->type->next))
2324           return RESULT_TYPE_NONE;
2325         else
2326           return getResultTypeFromType (currFunc->type->next);
2327       case '[':
2328         if (!IS_ARRAY (LTYPE (tree)))
2329           return resultType;
2330         if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2331           return RESULT_TYPE_CHAR;
2332         return resultType;
2333       default:
2334         return resultType;
2335     }
2336 }
2337
2338 /*------------------------------------------------------------------*/
2339 /* gatherImplicitVariables: assigns correct type information to     */
2340 /*            symbols and values created by replaceAstWithTemporary */
2341 /*            and adds the symbols to the declarations list of the  */
2342 /*            innermost block that contains them                    */
2343 /*------------------------------------------------------------------*/
2344 void
2345 gatherImplicitVariables (ast * tree, ast * block)
2346 {
2347   if (!tree)
2348     return;
2349
2350   if (tree->type == EX_OP && tree->opval.op == BLOCK)
2351     {
2352       /* keep track of containing scope */
2353       block = tree;
2354     }
2355   if (tree->type == EX_OP && tree->opval.op == '=' &&
2356       tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2357     {
2358       symbol *assignee = tree->left->opval.val->sym;
2359
2360       /* special case for assignment to compiler-generated temporary variable:
2361          compute type of RHS, and set the symbol's type to match */
2362       if (assignee->type == NULL && assignee->infertype) {
2363         ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2364
2365         if (dtr != tree->right)
2366           tree->right = dtr;
2367
2368         assignee->type = copyLinkChain(TTYPE(dtr));
2369         assignee->etype = getSpec(assignee->type);
2370         SPEC_SCLS (assignee->etype) = S_AUTO;
2371         SPEC_OCLS (assignee->etype) = NULL;
2372         SPEC_EXTR (assignee->etype) = 0;
2373         SPEC_STAT (assignee->etype) = 0;
2374         SPEC_VOLATILE (assignee->etype) = 0;
2375         SPEC_ABSA (assignee->etype) = 0;
2376
2377         wassertl(block != NULL, "implicit variable not contained in block");
2378         wassert(assignee->next == NULL);
2379         if (block != NULL) {
2380           symbol **decl = &(block->values.sym);
2381
2382           while (*decl) {
2383             wassert(*decl != assignee);  /* should not already be in list */
2384             decl = &( (*decl)->next );
2385           }
2386
2387           *decl = assignee;
2388         }
2389       }
2390     }
2391   if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2392       tree->opval.val->type == NULL &&
2393       tree->opval.val->sym &&
2394       tree->opval.val->sym->infertype)
2395     {
2396       /* fixup type of value for compiler-inferred temporary var */
2397       tree->opval.val->type = tree->opval.val->sym->type;
2398       tree->opval.val->etype = tree->opval.val->sym->etype;
2399     }
2400
2401   gatherImplicitVariables(tree->left, block);
2402   gatherImplicitVariables(tree->right, block);
2403 }
2404
2405 /*--------------------------------------------------------------------*/
2406 /* decorateType - compute type for this tree, also does type checking.*/
2407 /* This is done bottom up, since type has to flow upwards.            */
2408 /* resultType flows top-down and forces e.g. char-arithmetic, if the  */
2409 /* result is a char and the operand(s) are int's.                     */
2410 /* It also does constant folding, and parameter checking.             */
2411 /*--------------------------------------------------------------------*/
2412 ast *
2413 decorateType (ast * tree, RESULT_TYPE resultType)
2414 {
2415   int parmNumber;
2416   sym_link *p;
2417   RESULT_TYPE resultTypeProp;
2418
2419   if (!tree)
2420     return tree;
2421
2422   /* if already has type then do nothing */
2423   if (tree->decorated)
2424     return tree;
2425
2426   tree->decorated = 1;
2427
2428 #if 0
2429   /* print the line          */
2430   /* if not block & function */
2431   if (tree->type == EX_OP &&
2432       (tree->opval.op != FUNCTION &&
2433        tree->opval.op != BLOCK &&
2434        tree->opval.op != NULLOP))
2435     {
2436       filename = tree->filename;
2437       lineno = tree->lineno;
2438     }
2439 #endif
2440
2441   /* if any child is an error | this one is an error do nothing */
2442   if (tree->isError ||
2443       (tree->left && tree->left->isError) ||
2444       (tree->right && tree->right->isError))
2445     return tree;
2446
2447 /*------------------------------------------------------------------*/
2448 /*----------------------------*/
2449 /*   leaf has been reached    */
2450 /*----------------------------*/
2451   lineno = tree->lineno;
2452   /* if this is of type value */
2453   /* just get the type        */
2454   if (tree->type == EX_VALUE)
2455     {
2456
2457       if (IS_LITERAL (tree->opval.val->etype))
2458         {
2459
2460           /* if this is a character array then declare it */
2461           if (IS_ARRAY (tree->opval.val->type))
2462             tree->opval.val = stringToSymbol (tree->opval.val);
2463
2464           /* otherwise just copy the type information */
2465           COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2466           return tree;
2467         }
2468
2469       if (tree->opval.val->sym)
2470         {
2471           /* if the undefined flag is set then give error message */
2472           if (tree->opval.val->sym->undefined)
2473             {
2474               werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2475               /* assume int */
2476               TTYPE (tree) = TETYPE (tree) =
2477                 tree->opval.val->type = tree->opval.val->sym->type =
2478                 tree->opval.val->etype = tree->opval.val->sym->etype =
2479                 copyLinkChain (INTTYPE);
2480             }
2481           else if (tree->opval.val->sym->implicit)
2482             {
2483               /* if implicit i.e. struct/union member then no type */
2484               TTYPE (tree) = TETYPE (tree) = NULL;
2485             }
2486           else
2487             {
2488               /* copy the type from the value into the ast */
2489               COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2490
2491               /* and mark the symbol as referenced */
2492               tree->opval.val->sym->isref = 1;
2493             }
2494         }
2495       else
2496         wassert(0); /* unreached: all values are literals or symbols */
2497
2498       return tree;
2499     }
2500
2501   /* if type link for the case of cast */
2502   if (tree->type == EX_LINK)
2503     {
2504       COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2505       return tree;
2506     }
2507
2508   {
2509     ast *dtl, *dtr;
2510
2511     #if 0
2512     if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2513       {
2514         if (tree->left && tree->left->type == EX_OPERAND
2515             && (tree->left->opval.op == INC_OP
2516                 || tree->left->opval.op == DEC_OP)
2517             && tree->left->left)
2518           {
2519             tree->left->right = tree->left->left;
2520             tree->left->left = NULL;
2521           }
2522         if (tree->right && tree->right->type == EX_OPERAND
2523             && (tree->right->opval.op == INC_OP
2524                 || tree->right->opval.op == DEC_OP)
2525             && tree->right->left)
2526           {
2527             tree->right->right = tree->right->left;
2528             tree->right->left = NULL;
2529           }
2530       }
2531     #endif
2532
2533     /* Before decorating the left branch we've to decide in dependence
2534        upon tree->opval.op, if resultType can be propagated */
2535     resultTypeProp = resultTypePropagate (tree, resultType);
2536
2537     if (tree->opval.op == '?')
2538       dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2539     else
2540       dtl = decorateType (tree->left, resultTypeProp);
2541
2542     /* if an array node, we may need to swap branches */
2543     if (tree->opval.op == '[')
2544       {
2545         /* determine which is the array & which the index */
2546         if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2547             IS_INTEGRAL (LTYPE (tree)))
2548           {
2549             ast *tempTree = tree->left;
2550             tree->left = tree->right;
2551             tree->right = tempTree;
2552           }
2553       }
2554
2555     /* After decorating the left branch there's type information available
2556        in tree->left->?type. If the op is e.g. '=' we extract the type
2557        information from there and propagate it to the right branch. */
2558     resultTypeProp = getLeftResultType (tree, resultTypeProp);
2559
2560     switch (tree->opval.op)
2561       {
2562         case '?':
2563           /* delay right side for '?' operator since conditional macro
2564              expansions might rely on this */
2565           dtr = tree->right;
2566           break;
2567         case CALL:
2568           /* decorate right side for CALL (parameter list) in processParms();
2569              there is resultType available */
2570           dtr = tree->right;
2571           break;
2572         default:
2573           dtr = decorateType (tree->right, resultTypeProp);
2574           break;
2575       }
2576
2577     /* this is to take care of situations
2578        when the tree gets rewritten */
2579     if (dtl != tree->left)
2580       tree->left = dtl;
2581     if (dtr != tree->right)
2582       tree->right = dtr;
2583     if ((dtl && dtl->isError) || (dtr && dtr->isError))
2584       return tree;
2585   }
2586
2587   /* depending on type of operator do */
2588
2589   switch (tree->opval.op)
2590     {
2591         /*------------------------------------------------------------------*/
2592         /*----------------------------*/
2593         /*        array node          */
2594         /*----------------------------*/
2595     case '[':
2596
2597       /* first check if this is a array or a pointer */
2598       if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2599         {
2600           werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2601           goto errorTreeReturn;
2602         }
2603
2604       /* check if the type of the idx */
2605       if (!IS_INTEGRAL (RTYPE (tree)))
2606         {
2607           werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2608           goto errorTreeReturn;
2609         }
2610
2611       /* if the left is an rvalue then error */
2612       if (LRVAL (tree))
2613         {
2614           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2615           goto errorTreeReturn;
2616         }
2617
2618       if (IS_LITERAL (RTYPE (tree)))
2619         {
2620           int arrayIndex = (int) floatFromVal (valFromType (RETYPE (tree)));
2621           int arraySize = DCL_ELEM (LTYPE (tree));
2622           if (arraySize && arrayIndex >= arraySize)
2623             {
2624               werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2625             }
2626         }
2627
2628       RRVAL (tree) = 1;
2629       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2630       SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2631       return tree;
2632
2633       /*------------------------------------------------------------------*/
2634       /*----------------------------*/
2635       /*      struct/union          */
2636       /*----------------------------*/
2637     case '.':
2638       /* if this is not a structure */
2639       if (!IS_STRUCT (LTYPE (tree)))
2640         {
2641           werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2642           goto errorTreeReturn;
2643         }
2644       TTYPE (tree) = structElemType (LTYPE (tree),
2645                                      (tree->right->type == EX_VALUE ?
2646                                tree->right->opval.val : NULL));
2647       TETYPE (tree) = getSpec (TTYPE (tree));
2648       return tree;
2649
2650       /*------------------------------------------------------------------*/
2651       /*----------------------------*/
2652       /*    struct/union pointer    */
2653       /*----------------------------*/
2654     case PTR_OP:
2655       /* if not pointer to a structure */
2656       if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2657         {
2658           werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2659           goto errorTreeReturn;
2660         }
2661
2662       if (!IS_STRUCT (LTYPE (tree)->next))
2663         {
2664           werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2665           goto errorTreeReturn;
2666         }
2667
2668       TTYPE (tree) = structElemType (LTYPE (tree)->next,
2669                                      (tree->right->type == EX_VALUE ?
2670                                tree->right->opval.val : NULL));
2671       TETYPE (tree) = getSpec (TTYPE (tree));
2672
2673       /* adjust the storage class */
2674       switch (DCL_TYPE(tree->left->ftype)) {
2675       case POINTER:
2676         SPEC_SCLS(TETYPE(tree)) = S_DATA;
2677         break;
2678       case FPOINTER:
2679         SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2680         break;
2681       case CPOINTER:
2682         SPEC_SCLS(TETYPE(tree)) = S_CODE;
2683         break;
2684       case GPOINTER:
2685         SPEC_SCLS (TETYPE (tree)) = 0;
2686         break;
2687       case PPOINTER:
2688         SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2689         break;
2690       case IPOINTER:
2691         SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2692         break;
2693       case EEPPOINTER:
2694         SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2695         break;
2696       case UPOINTER:
2697         SPEC_SCLS (TETYPE (tree)) = 0;
2698         break;
2699       case ARRAY:
2700       case FUNCTION:
2701         break;
2702       }
2703
2704       /* This breaks with extern declarations, bitfields, and perhaps other */
2705       /* cases (gcse). Let's leave this optimization disabled for now and   */
2706       /* ponder if there's a safe way to do this. -- EEP                    */
2707       #if 0
2708       if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2709           && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2710         {
2711             /* If defined    struct type at addr var
2712                then rewrite  (&struct var)->member
2713                as            temp
2714                and define    membertype at (addr+offsetof(struct var,member)) temp
2715             */
2716             symbol *sym;
2717             symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2718                                                 AST_SYMBOL(tree->right));
2719
2720             sym = newSymbol(genSymName (0), 0);
2721             sym->type = TTYPE (tree);
2722             sym->etype = getSpec(sym->type);
2723             sym->lineDef = tree->lineno;
2724             sym->cdef = 1;
2725             sym->isref = 1;
2726             SPEC_STAT (sym->etype) = 1;
2727             SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2728                                      + element->offset;
2729             SPEC_ABSA(sym->etype) = 1;
2730             addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2731             allocGlobal (sym);
2732
2733             AST_VALUE (tree) = symbolVal(sym);
2734             TLVAL (tree) = 1;
2735             TRVAL (tree) = 0;
2736             tree->type = EX_VALUE;
2737             tree->left = NULL;
2738             tree->right = NULL;
2739         }
2740       #endif
2741
2742       return tree;
2743
2744       /*------------------------------------------------------------------*/
2745       /*----------------------------*/
2746       /*  ++/-- operation           */
2747       /*----------------------------*/
2748     case INC_OP:
2749     case DEC_OP:
2750       {
2751         sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2752         COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2753         if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2754           werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2755
2756         if (tree->right)
2757           RLVAL (tree) = 1;
2758         else
2759           LLVAL (tree) = 1;
2760         return tree;
2761       }
2762
2763       /*------------------------------------------------------------------*/
2764       /*----------------------------*/
2765       /*  bitwise and               */
2766       /*----------------------------*/
2767     case '&':                   /* can be unary   */
2768       /* if right is NULL then unary operation  */
2769       if (tree->right)          /* not an unary operation */
2770         {
2771
2772           if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2773             {
2774               werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2775               werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2776               printTypeChain (LTYPE (tree), stderr);
2777               fprintf (stderr, ",");
2778               printTypeChain (RTYPE (tree), stderr);
2779               fprintf (stderr, "\n");
2780               goto errorTreeReturn;
2781             }
2782
2783           /* if they are both literal */
2784           if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2785             {
2786               tree->type = EX_VALUE;
2787               tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2788                                           valFromType (RETYPE (tree)), '&');
2789
2790               tree->right = tree->left = NULL;
2791               TETYPE (tree) = tree->opval.val->etype;
2792               TTYPE (tree) = tree->opval.val->type;
2793               return tree;
2794             }
2795
2796           /* see if this is a GETHBIT operation if yes
2797              then return that */
2798           {
2799             ast *otree = optimizeGetHbit (tree, resultType);
2800
2801             if (otree != tree)
2802               return decorateType (otree, RESULT_TYPE_NONE);
2803           }
2804
2805           /* see if this is a GETABIT operation if yes
2806              then return that */
2807           {
2808             ast *otree = optimizeGetAbit (tree, resultType);
2809
2810             if (otree != tree)
2811               return decorateType (otree, RESULT_TYPE_NONE);
2812           }
2813
2814           /* see if this is a GETBYTE operation if yes
2815              then return that */
2816           {
2817             ast *otree = optimizeGetByte (tree, resultType);
2818
2819             if (otree != tree)
2820               return decorateType (otree, RESULT_TYPE_NONE);
2821           }
2822
2823           /* see if this is a GETWORD operation if yes
2824              then return that */
2825           {
2826             ast *otree = optimizeGetWord (tree, resultType);
2827
2828             if (otree != tree)
2829               return decorateType (otree, RESULT_TYPE_NONE);
2830           }
2831
2832           /* if left is a literal exchange left & right */
2833           if (IS_LITERAL (LTYPE (tree)))
2834             {
2835               ast *tTree = tree->left;
2836               tree->left = tree->right;
2837               tree->right = tTree;
2838             }
2839
2840           /* if right is a literal and */
2841           /* we can find a 2nd literal in an and-tree then */
2842           /* rearrange the tree */
2843           if (IS_LITERAL (RTYPE (tree)))
2844             {
2845               ast *parent;
2846               ast *litTree = searchLitOp (tree, &parent, "&");
2847               if (litTree)
2848                 {
2849                   DEBUG_CF("&")
2850                   ast *tTree = litTree->left;
2851                   litTree->left = tree->right;
2852                   tree->right = tTree;
2853                   /* both operands in litTree are literal now */
2854                   decorateType (parent, resultType);
2855                 }
2856             }
2857
2858           LRVAL (tree) = RRVAL (tree) = 1;
2859
2860           TTYPE (tree) = computeType (LTYPE (tree),
2861                                       RTYPE (tree),
2862                                       resultType,
2863                                       tree->opval.op);
2864           TETYPE (tree) = getSpec (TTYPE (tree));
2865
2866           return tree;
2867         }
2868
2869       /*------------------------------------------------------------------*/
2870       /*----------------------------*/
2871       /*  address of                */
2872       /*----------------------------*/
2873       p = newLink (DECLARATOR);
2874       /* if bit field then error */
2875       if (IS_BITVAR (tree->left->etype))
2876         {
2877           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2878           goto errorTreeReturn;
2879         }
2880
2881       if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2882         {
2883           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2884           goto errorTreeReturn;
2885         }
2886
2887       if (IS_FUNC (LTYPE (tree)))
2888         {
2889           // this ought to be ignored
2890           return (tree->left);
2891         }
2892
2893       if (IS_LITERAL(LTYPE(tree)))
2894         {
2895           werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2896           goto errorTreeReturn;
2897         }
2898
2899      if (LRVAL (tree))
2900         {
2901           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2902           goto errorTreeReturn;
2903         }
2904       if (!LETYPE (tree))
2905         DCL_TYPE (p) = POINTER;
2906       else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2907         DCL_TYPE (p) = CPOINTER;
2908       else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2909         DCL_TYPE (p) = FPOINTER;
2910       else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2911         DCL_TYPE (p) = PPOINTER;
2912       else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2913         DCL_TYPE (p) = IPOINTER;
2914       else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2915         DCL_TYPE (p) = EEPPOINTER;
2916       else if (SPEC_OCLS(tree->left->etype))
2917           DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2918       else
2919           DCL_TYPE (p) = POINTER;
2920
2921       if (IS_AST_SYM_VALUE (tree->left))
2922         {
2923           AST_SYMBOL (tree->left)->addrtaken = 1;
2924           AST_SYMBOL (tree->left)->allocreq = 1;
2925         }
2926
2927       p->next = LTYPE (tree);
2928       TTYPE (tree) = p;
2929       TETYPE (tree) = getSpec (TTYPE (tree));
2930       LLVAL (tree) = 1;
2931       TLVAL (tree) = 1;
2932
2933       #if 0
2934       if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2935           && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2936         {
2937           symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2938                                       AST_SYMBOL(tree->left->right));
2939           AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2940                                     valueFromLit(element->offset));
2941           tree->left = NULL;
2942           tree->right = NULL;
2943           tree->type = EX_VALUE;
2944           tree->values.literalFromCast = 1;
2945         }
2946       #endif
2947
2948       return tree;
2949
2950       /*------------------------------------------------------------------*/
2951       /*----------------------------*/
2952       /*  bitwise or                */
2953       /*----------------------------*/
2954     case '|':
2955       /* if the rewrite succeeds then don't go any further */
2956       {
2957         ast *wtree = optimizeRRCRLC (tree);
2958         if (wtree != tree)
2959           return decorateType (wtree, RESULT_TYPE_NONE);
2960
2961         wtree = optimizeSWAP (tree);
2962         if (wtree != tree)
2963           return decorateType (wtree, RESULT_TYPE_NONE);
2964       }
2965
2966       /* if left is a literal exchange left & right */
2967       if (IS_LITERAL (LTYPE (tree)))
2968         {
2969           ast *tTree = tree->left;
2970           tree->left = tree->right;
2971           tree->right = tTree;
2972         }
2973
2974       /* if right is a literal and */
2975       /* we can find a 2nd literal in an or-tree then */
2976       /* rearrange the tree */
2977       if (IS_LITERAL (RTYPE (tree)))
2978         {
2979           ast *parent;
2980           ast *litTree = searchLitOp (tree, &parent, "|");
2981           if (litTree)
2982             {
2983               DEBUG_CF("|")
2984               ast *tTree = litTree->left;
2985               litTree->left = tree->right;
2986               tree->right = tTree;
2987               /* both operands in tTree are literal now */
2988               decorateType (parent, resultType);
2989             }
2990         }
2991       /* fall through */
2992
2993       /*------------------------------------------------------------------*/
2994       /*----------------------------*/
2995       /*  bitwise xor               */
2996       /*----------------------------*/
2997     case '^':
2998       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2999         {
3000           werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3001           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3002           printTypeChain (LTYPE (tree), stderr);
3003           fprintf (stderr, ",");
3004           printTypeChain (RTYPE (tree), stderr);
3005           fprintf (stderr, "\n");
3006           goto errorTreeReturn;
3007         }
3008
3009       /* if they are both literal then rewrite the tree */
3010       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3011         {
3012           tree->type = EX_VALUE;
3013           tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3014                                         valFromType (RETYPE (tree)),
3015                                         tree->opval.op);
3016           tree->right = tree->left = NULL;
3017           TETYPE (tree) = tree->opval.val->etype;
3018           TTYPE (tree) = tree->opval.val->type;
3019           return tree;
3020         }
3021
3022       /* if left is a literal exchange left & right */
3023       if (IS_LITERAL (LTYPE (tree)))
3024         {
3025           ast *tTree = tree->left;
3026           tree->left = tree->right;
3027           tree->right = tTree;
3028         }
3029
3030       /* if right is a literal and */
3031       /* we can find a 2nd literal in a xor-tree then */
3032       /* rearrange the tree */
3033       if (IS_LITERAL (RTYPE (tree)) &&
3034           tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3035         {
3036           ast *parent;
3037           ast *litTree = searchLitOp (tree, &parent, "^");
3038           if (litTree)
3039             {
3040               DEBUG_CF("^")
3041               ast *tTree = litTree->left;
3042               litTree->left = tree->right;
3043               tree->right = tTree;
3044               /* both operands in litTree are literal now */
3045               decorateType (parent, resultType);
3046             }
3047         }
3048
3049       LRVAL (tree) = RRVAL (tree) = 1;
3050
3051       TTYPE (tree) = computeType (LTYPE (tree),
3052                                   RTYPE (tree),
3053                                   resultType,
3054                                   tree->opval.op);
3055       TETYPE (tree) = getSpec (TTYPE (tree));
3056
3057       return tree;
3058
3059       /*------------------------------------------------------------------*/
3060       /*----------------------------*/
3061       /*  division                  */
3062       /*----------------------------*/
3063     case '/':
3064       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3065         {
3066           werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3067           goto errorTreeReturn;
3068         }
3069       /* if they are both literal then */
3070       /* rewrite the tree */
3071       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3072         {
3073           tree->type = EX_VALUE;
3074           tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3075                                     valFromType (RETYPE (tree)));
3076           tree->right = tree->left = NULL;
3077           TETYPE (tree) = getSpec (TTYPE (tree) =
3078                                    tree->opval.val->type);
3079           return tree;
3080         }
3081
3082       LRVAL (tree) = RRVAL (tree) = 1;
3083
3084       TETYPE (tree) = getSpec (TTYPE (tree) =
3085                                computeType (LTYPE (tree),
3086                                             RTYPE (tree),
3087                                             resultType,
3088                                             tree->opval.op));
3089
3090       /* if right is a literal and */
3091       /* left is also a division by a literal then */
3092       /* rearrange the tree */
3093       if (IS_LITERAL (RTYPE (tree))
3094           /* avoid infinite loop */
3095           && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 1)
3096         {
3097           ast *parent;
3098           ast *litTree = searchLitOp (tree, &parent, "/");
3099           if (litTree)
3100             {
3101               if (IS_LITERAL (RTYPE (litTree)))
3102                 {
3103                   /* foo_div */
3104                   DEBUG_CF("div r")
3105                   litTree->right = newNode ('*',
3106                                             litTree->right,
3107                                             copyAst (tree->right));
3108                   litTree->right->lineno = tree->lineno;
3109
3110                   tree->right->opval.val = constVal ("1");
3111                   decorateType (parent, resultType);
3112                 }
3113               else
3114                 {
3115                   /* litTree->left is literal: no gcse possible.
3116                      We can't call decorateType(parent, RESULT_TYPE_NONE), because
3117                      this would cause an infinit loop. */
3118                   parent->decorated = 1;
3119                   decorateType (litTree, resultType);
3120                 }
3121             }
3122         }
3123
3124       return tree;
3125
3126       /*------------------------------------------------------------------*/
3127       /*----------------------------*/
3128       /*            modulus         */
3129       /*----------------------------*/
3130     case '%':
3131       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3132         {
3133           werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3134           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3135           printTypeChain (LTYPE (tree), stderr);
3136           fprintf (stderr, ",");
3137           printTypeChain (RTYPE (tree), stderr);
3138           fprintf (stderr, "\n");
3139           goto errorTreeReturn;
3140         }
3141       /* if they are both literal then */
3142       /* rewrite the tree */
3143       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3144         {
3145           tree->type = EX_VALUE;
3146           tree->opval.val = valMod (valFromType (LETYPE (tree)),
3147                                     valFromType (RETYPE (tree)));
3148           tree->right = tree->left = NULL;
3149           TETYPE (tree) = getSpec (TTYPE (tree) =
3150                                    tree->opval.val->type);
3151           return tree;
3152         }
3153       LRVAL (tree) = RRVAL (tree) = 1;
3154       TETYPE (tree) = getSpec (TTYPE (tree) =
3155                                computeType (LTYPE (tree),
3156                                             RTYPE (tree),
3157                                             resultType,
3158                                             tree->opval.op));
3159       return tree;
3160
3161       /*------------------------------------------------------------------*/
3162       /*----------------------------*/
3163       /*  address dereference       */
3164       /*----------------------------*/
3165     case '*':                   /* can be unary  : if right is null then unary operation */
3166       if (!tree->right)
3167         {
3168           if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3169             {
3170               werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3171               goto errorTreeReturn;
3172             }
3173
3174           if (LRVAL (tree))
3175             {
3176               werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3177               goto errorTreeReturn;
3178             }
3179           if (IS_ADDRESS_OF_OP(tree->left))
3180             {
3181               /* replace *&obj with obj */
3182               return tree->left->left;
3183             }
3184           TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3185           TETYPE (tree) = getSpec (TTYPE (tree));
3186           /* adjust the storage class */
3187           switch (DCL_TYPE(tree->left->ftype)) {
3188             case POINTER:
3189               SPEC_SCLS(TETYPE(tree)) = S_DATA;
3190               break;
3191             case FPOINTER:
3192               SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3193               break;
3194             case CPOINTER:
3195               SPEC_SCLS(TETYPE(tree)) = S_CODE;
3196               break;
3197             case GPOINTER:
3198               SPEC_SCLS (TETYPE (tree)) = 0;
3199               break;
3200             case PPOINTER:
3201               SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3202               break;
3203             case IPOINTER:
3204               SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3205               break;
3206             case EEPPOINTER:
3207               SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3208               break;
3209             case UPOINTER:
3210               SPEC_SCLS (TETYPE (tree)) = 0;
3211               break;
3212             case ARRAY:
3213             case FUNCTION:
3214               break;
3215           }
3216           return tree;
3217         }
3218
3219       /*------------------------------------------------------------------*/
3220       /*----------------------------*/
3221       /*      multiplication        */
3222       /*----------------------------*/
3223       if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3224         {
3225           werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3226           goto errorTreeReturn;
3227         }
3228
3229       /* if they are both literal then */
3230       /* rewrite the tree */
3231       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3232         {
3233           tree->type = EX_VALUE;
3234           tree->opval.val = valMult (valFromType (LETYPE (tree)),
3235                                      valFromType (RETYPE (tree)));
3236           tree->right = tree->left = NULL;
3237           TETYPE (tree) = getSpec (TTYPE (tree) =
3238                                    tree->opval.val->type);
3239           return tree;
3240         }
3241
3242       /* if left is a literal exchange left & right */
3243       if (IS_LITERAL (LTYPE (tree)))
3244         {
3245           ast *tTree = tree->left;
3246           tree->left = tree->right;
3247           tree->right = tTree;
3248         }
3249
3250       /* if right is a literal and */
3251       /* we can find a 2nd literal in a mul-tree then */
3252       /* rearrange the tree */
3253       if (IS_LITERAL (RTYPE (tree)))
3254         {
3255           ast *parent;
3256           ast *litTree = searchLitOp (tree, &parent, "*");
3257           if (litTree)
3258             {
3259               DEBUG_CF("mul")
3260               ast *tTree = litTree->left;
3261               litTree->left = tree->right;
3262               tree->right = tTree;
3263               /* both operands in litTree are literal now */
3264               decorateType (parent, resultType);
3265             }
3266         }
3267
3268       LRVAL (tree) = RRVAL (tree) = 1;
3269       tree->left  = addCast (tree->left,  resultType, FALSE);
3270       tree->right = addCast (tree->right, resultType, FALSE);
3271       TETYPE (tree) = getSpec (TTYPE (tree) =
3272                                    computeType (LTYPE (tree),
3273                                                 RTYPE (tree),
3274                                                 resultType,
3275                                                 tree->opval.op));
3276
3277       return tree;
3278
3279       /*------------------------------------------------------------------*/
3280       /*----------------------------*/
3281       /*    unary '+' operator      */
3282       /*----------------------------*/
3283     case '+':
3284       /* if unary plus */
3285       if (!tree->right)
3286         {
3287           if (!IS_ARITHMETIC (LTYPE (tree)))
3288             {
3289               werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3290               goto errorTreeReturn;
3291             }
3292
3293           /* if left is a literal then do it */
3294           if (IS_LITERAL (LTYPE (tree)))
3295             {
3296               tree->type = EX_VALUE;
3297               tree->opval.val = valFromType (LETYPE (tree));
3298               tree->left = NULL;
3299               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3300               return tree;
3301             }
3302           LRVAL (tree) = 1;
3303           COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3304           return tree;
3305         }
3306
3307       /*------------------------------------------------------------------*/
3308       /*----------------------------*/
3309       /*      addition              */
3310       /*----------------------------*/
3311
3312       /* this is not a unary operation */
3313       /* if both pointers then problem */
3314       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3315           (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3316         {
3317           werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3318           goto errorTreeReturn;
3319         }
3320
3321       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3322           !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3323         {
3324           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3325           goto errorTreeReturn;
3326         }
3327
3328       if (!IS_ARITHMETIC (RTYPE (tree)) &&
3329           !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3330         {
3331           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3332           goto errorTreeReturn;
3333         }
3334       /* if they are both literal then */
3335       /* rewrite the tree */
3336       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3337         {
3338           tree->type = EX_VALUE;
3339           tree->left  = addCast (tree->left,  resultType, TRUE);
3340           tree->right = addCast (tree->right, resultType, TRUE);
3341           tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3342                                      valFromType (RETYPE (tree)));
3343           tree->right = tree->left = NULL;
3344           TETYPE (tree) = getSpec (TTYPE (tree) =
3345                                    tree->opval.val->type);
3346           return tree;
3347         }
3348
3349       /* if the right is a pointer or left is a literal
3350          xchange left & right */
3351       if (IS_ARRAY (RTYPE (tree)) ||
3352           IS_PTR (RTYPE (tree)) ||
3353           IS_LITERAL (LTYPE (tree)))
3354         {
3355           ast *tTree = tree->left;
3356           tree->left = tree->right;
3357           tree->right = tTree;
3358         }
3359
3360       /* if right is a literal and */
3361       /* left is also an addition/subtraction with a literal then */
3362       /* rearrange the tree */
3363       if (IS_LITERAL (RTYPE (tree)))
3364         {
3365           ast *litTree, *parent;
3366           litTree = searchLitOp (tree, &parent, "+-");
3367           if (litTree)
3368             {
3369               if (litTree->opval.op == '+')
3370                 {
3371                   /* foo_aa */
3372                   DEBUG_CF("+ 1 AA")
3373                   ast *tTree = litTree->left;
3374                   litTree->left = tree->right;
3375                   tree->right = tree->left;
3376                   tree->left = tTree;
3377                 }
3378               else if (litTree->opval.op == '-')
3379                 {
3380                   if (IS_LITERAL (RTYPE (litTree)))
3381                     {
3382                       DEBUG_CF("+ 2 ASR")
3383                       /* foo_asr */
3384                       ast *tTree = litTree->left;
3385                       litTree->left = tree->right;
3386                       tree->right = tTree;
3387                     }
3388                   else
3389                     {
3390                       DEBUG_CF("+ 3 ASL")
3391                       /* foo_asl */
3392                       ast *tTree = litTree->right;
3393                       litTree->right = tree->right;
3394                       tree->right = tTree;
3395                       litTree->opval.op = '+';
3396                       tree->opval.op = '-';
3397                     }
3398                 }
3399               decorateType (parent, resultType);
3400             }
3401         }
3402
3403       LRVAL (tree) = RRVAL (tree) = 1;
3404       /* if the left is a pointer */
3405       if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3406         TETYPE (tree) = getSpec (TTYPE (tree) =
3407                                  LTYPE (tree));
3408       else
3409         {
3410           tree->left  = addCast (tree->left,  resultType, TRUE);
3411           tree->right = addCast (tree->right, resultType, TRUE);
3412           TETYPE (tree) = getSpec (TTYPE (tree) =
3413                                      computeType (LTYPE (tree),
3414                                                   RTYPE (tree),
3415                                                   resultType,
3416                                                   tree->opval.op));
3417         }
3418
3419       return tree;
3420
3421       /*------------------------------------------------------------------*/
3422       /*----------------------------*/
3423       /*      unary '-'             */
3424       /*----------------------------*/
3425     case '-':                   /* can be unary   */
3426       /* if right is null then unary */
3427       if (!tree->right)
3428         {
3429
3430           if (!IS_ARITHMETIC (LTYPE (tree)))
3431             {
3432               werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3433               goto errorTreeReturn;
3434             }
3435
3436           /* if left is a literal then do it */
3437           if (IS_LITERAL (LTYPE (tree)))
3438             {
3439               tree->type = EX_VALUE;
3440               tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3441               tree->left = NULL;
3442               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3443               return tree;
3444             }
3445           tree->left  = addCast (tree->left, resultType, TRUE);
3446           TETYPE (tree) = getSpec (TTYPE (tree) =
3447                                      computeType (LTYPE (tree),
3448                                                   NULL,
3449                                                   resultType,
3450                                                   tree->opval.op));
3451           LRVAL (tree) = 1;
3452           return tree;
3453         }
3454
3455       /*------------------------------------------------------------------*/
3456       /*----------------------------*/
3457       /*    subtraction             */
3458       /*----------------------------*/
3459
3460       if (!(IS_PTR (LTYPE (tree)) ||
3461             IS_ARRAY (LTYPE (tree)) ||
3462             IS_ARITHMETIC (LTYPE (tree))))
3463         {
3464           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3465           goto errorTreeReturn;
3466         }
3467
3468       if (!(IS_PTR (RTYPE (tree)) ||
3469             IS_ARRAY (RTYPE (tree)) ||
3470             IS_ARITHMETIC (RTYPE (tree))))
3471         {
3472           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3473           goto errorTreeReturn;
3474         }
3475
3476       if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3477           !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3478             IS_INTEGRAL (RTYPE (tree))))
3479         {
3480           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3481           goto errorTreeReturn;
3482         }
3483
3484       /* if they are both literal then */
3485       /* rewrite the tree */
3486       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3487         {
3488           tree->type = EX_VALUE;
3489           tree->left  = addCast (tree->left,  resultType, TRUE);
3490           tree->right = addCast (tree->right, resultType, TRUE);
3491           tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3492                                       valFromType (RETYPE (tree)));
3493           tree->right = tree->left = NULL;
3494           TETYPE (tree) = getSpec (TTYPE (tree) =
3495                                    tree->opval.val->type);
3496           return tree;
3497         }
3498
3499       /* if the left & right are equal then zero */
3500       if (isAstEqual (tree->left, tree->right))
3501         {
3502           tree->type = EX_VALUE;
3503           tree->left = tree->right = NULL;
3504           tree->opval.val = constVal ("0");
3505           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3506           return tree;
3507         }
3508
3509       /* if both of them are pointers or arrays then */
3510       /* the result is going to be an integer        */
3511       if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3512           (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3513         TETYPE (tree) = TTYPE (tree) = newIntLink ();
3514       else
3515         /* if only the left is a pointer */
3516         /* then result is a pointer      */
3517       if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3518         TETYPE (tree) = getSpec (TTYPE (tree) =
3519                                  LTYPE (tree));
3520       else
3521         {
3522           tree->left  = addCast (tree->left,  resultType, TRUE);
3523           tree->right = addCast (tree->right, resultType, TRUE);
3524
3525           TETYPE (tree) = getSpec (TTYPE (tree) =
3526                                      computeType (LTYPE (tree),
3527                                                   RTYPE (tree),
3528                                                   resultType,
3529                                                   tree->opval.op));
3530         }
3531
3532       LRVAL (tree) = RRVAL (tree) = 1;
3533
3534       /* if right is a literal and */
3535       /* left is also an addition/subtraction with a literal then */
3536       /* rearrange the tree */
3537       if (IS_LITERAL (RTYPE (tree))
3538           /* avoid infinite loop */
3539           && (TYPE_TARGET_ULONG) floatFromVal (tree->right->opval.val) != 0)
3540         {
3541           ast *litTree, *litParent;
3542           litTree = searchLitOp (tree, &litParent, "+-");
3543           if (litTree)
3544             {
3545               if (litTree->opval.op == '+')
3546                 {
3547                   /* foo_sa */
3548                   DEBUG_CF("- 1 SA")
3549                   ast *tTree = litTree->left;
3550                   litTree->left = litTree->right;
3551                   litTree->right = tree->right;
3552                   tree->right = tTree;
3553                   tree->opval.op = '+';
3554                   litTree->opval.op = '-';
3555                 }
3556               else if (litTree->opval.op == '-')
3557                 {
3558                   if (IS_LITERAL (RTYPE (litTree)))
3559                     {
3560                       /* foo_ssr */
3561                       DEBUG_CF("- 2 SSR")
3562                       ast *tTree = litTree->left;
3563                       litTree->left = tree->right;
3564                       tree->right = litParent->left;
3565                       litParent->left = tTree;
3566                       litTree->opval.op = '+';
3567
3568                       tree->decorated = 0;
3569                       decorateType (tree, resultType);
3570                     }
3571                   else
3572                     {
3573                       /* foo_ssl */
3574                       DEBUG_CF("- 3 SSL")
3575                       ast *tTree = litTree->right;
3576                       litTree->right = tree->right;
3577                       tree->right = tTree;
3578                     }
3579                 }
3580               decorateType (litParent, resultType);
3581             }
3582         }
3583       return tree;
3584
3585       /*------------------------------------------------------------------*/
3586       /*----------------------------*/
3587       /*    complement              */
3588       /*----------------------------*/
3589     case '~':
3590       /* can be only integral type */
3591       if (!IS_INTEGRAL (LTYPE (tree)))
3592         {
3593           werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3594           goto errorTreeReturn;
3595         }
3596
3597       /* if left is a literal then do it */
3598       if (IS_LITERAL (LTYPE (tree)))
3599         {
3600           tree->type = EX_VALUE;
3601           tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3602           tree->left = NULL;
3603           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3604           return addCast (tree, resultType, TRUE);
3605         }
3606
3607       if (resultType == RESULT_TYPE_BIT &&
3608           IS_UNSIGNED (tree->left->etype) &&
3609           getSize (tree->left->etype) < INTSIZE)
3610         {
3611           /* promotion rules are responsible for this strange result:
3612              bit -> int -> ~int -> bit
3613              uchar -> int -> ~int -> bit
3614           */
3615           werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3616
3617           /* optimize bit-result, even if we optimize a buggy source */
3618           tree->type = EX_VALUE;
3619           tree->opval.val = constVal ("1");
3620         }
3621       else
3622         tree->left = addCast (tree->left, resultType, TRUE);
3623       LRVAL (tree) = 1;
3624       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3625       return tree;
3626
3627       /*------------------------------------------------------------------*/
3628       /*----------------------------*/
3629       /*           not              */
3630       /*----------------------------*/
3631     case '!':
3632       /* can be pointer */
3633       if (!IS_ARITHMETIC (LTYPE (tree)) &&
3634           !IS_PTR (LTYPE (tree)) &&
3635           !IS_ARRAY (LTYPE (tree)))
3636         {
3637           werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3638           goto errorTreeReturn;
3639         }
3640
3641       /* if left is another '!' */
3642       if (tree->left->opval.op == '!')
3643         {
3644           /* remove double '!!X' by 'X ? 1 : 0' */
3645           tree->opval.op = '?';
3646           tree->left  = tree->left->left;
3647           tree->right = newNode (':',
3648                                   newAst_VALUE (constVal ("1")),
3649                                   newAst_VALUE (constVal ("0")));
3650           tree->right->lineno = tree->lineno;
3651           tree->decorated = 0;
3652           return decorateType (tree, resultType);
3653         }
3654
3655       /* if left is a literal then do it */
3656       if (IS_LITERAL (LTYPE (tree)))
3657         {
3658           tree->type = EX_VALUE;
3659           tree->opval.val = valNot (valFromType (LETYPE (tree)));
3660           tree->left = NULL;
3661           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3662           return tree;
3663         }
3664       LRVAL (tree) = 1;
3665       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3666       return tree;
3667
3668       /*------------------------------------------------------------------*/
3669       /*----------------------------*/
3670       /*           shift            */
3671       /*----------------------------*/
3672     case RRC:
3673     case RLC:
3674     case SWAP:
3675       TTYPE (tree) = LTYPE (tree);
3676       TETYPE (tree) = LETYPE (tree);
3677       return tree;
3678
3679     case GETHBIT:
3680     case GETABIT:
3681       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3682       return tree;
3683
3684     case GETBYTE:
3685       TTYPE (tree) = TETYPE (tree) = newCharLink();
3686       return tree;
3687
3688     case GETWORD:
3689       TTYPE (tree) = TETYPE (tree) = newIntLink();
3690       return tree;
3691
3692     case LEFT_OP:
3693     case RIGHT_OP:
3694       if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3695         {
3696           werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3697           werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3698           printTypeChain (LTYPE (tree), stderr);
3699           fprintf (stderr, ",");
3700           printTypeChain (RTYPE (tree), stderr);
3701           fprintf (stderr, "\n");
3702           goto errorTreeReturn;
3703         }
3704
3705       /* make smaller type only if it's a LEFT_OP */
3706       if (tree->opval.op == LEFT_OP)
3707         tree->left = addCast (tree->left, resultType, TRUE);
3708
3709       /* if they are both literal then */
3710       /* rewrite the tree */
3711       if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3712         {
3713           tree->type = EX_VALUE;
3714           tree->opval.val = valShift (valFromType (LETYPE (tree)),
3715                                       valFromType (RETYPE (tree)),
3716                                       (tree->opval.op == LEFT_OP ? 1 : 0));
3717           tree->right = tree->left = NULL;
3718           TETYPE (tree) = getSpec (TTYPE (tree) =
3719                                    tree->opval.val->type);
3720           return tree;
3721         }
3722
3723       /* see if this is a GETBYTE operation if yes
3724          then return that */
3725       {
3726         ast *otree = optimizeGetByte (tree, resultType);
3727
3728         if (otree != tree)
3729           return decorateType (otree, RESULT_TYPE_NONE);
3730       }
3731
3732       /* see if this is a GETWORD operation if yes
3733          then return that */
3734       {
3735         ast *otree = optimizeGetWord (tree, resultType);
3736
3737         if (otree != tree)
3738           return decorateType (otree, RESULT_TYPE_NONE);
3739       }
3740
3741       LRVAL (tree) = RRVAL (tree) = 1;
3742       if (tree->opval.op == LEFT_OP)
3743         {
3744           TETYPE (tree) = getSpec (TTYPE (tree) =
3745                                        computeType (LTYPE (tree),
3746                                                     NULL,
3747                                                     resultType,
3748                                                     tree->opval.op));
3749         }
3750       else /* RIGHT_OP */
3751         {
3752           /* no promotion necessary */
3753           TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3754           if (IS_LITERAL (TTYPE (tree)))
3755             SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3756         }
3757
3758       /* if only the right side is a literal & we are
3759          shifting more than size of the left operand then zero */
3760       if (IS_LITERAL (RTYPE (tree)) &&
3761           ((TYPE_TARGET_ULONG) floatFromVal (valFromType (RETYPE (tree)))) >=
3762           (getSize (TETYPE (tree)) * 8))
3763         {
3764           if (tree->opval.op==LEFT_OP ||
3765               (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3766             {
3767               werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3768                       (tree->opval.op == LEFT_OP ? "left" : "right"));
3769               tree->type = EX_VALUE;
3770               tree->left = tree->right = NULL;
3771               tree->opval.val = constVal ("0");
3772               TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3773               return tree;
3774             }
3775         }
3776
3777       return tree;
3778
3779       /*------------------------------------------------------------------*/
3780       /*----------------------------*/
3781       /*         casting            */
3782       /*----------------------------*/
3783     case CAST:                  /* change the type   */
3784       /* cannot cast to an aggregate type */
3785       if (IS_AGGREGATE (LTYPE (tree)))
3786         {
3787           werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3788           goto errorTreeReturn;
3789         }
3790
3791       /* make sure the type is complete and sane */
3792       changePointer(LTYPE(tree));
3793       checkTypeSanity(LETYPE(tree), "(cast)");
3794
3795       /* if 'from' and 'to' are the same remove the superfluous cast, */
3796       /* this helps other optimizations */
3797       if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3798         {
3799           return tree->right;
3800         }
3801
3802       /* If code memory is read only, then pointers to code memory */
3803       /* implicitly point to constants -- make this explicit       */
3804       {
3805         sym_link *t = LTYPE(tree);
3806         while (t && t->next)
3807           {
3808             if (IS_CODEPTR(t) && port->mem.code_ro)
3809               {
3810                 if (IS_SPEC(t->next))
3811                   SPEC_CONST (t->next) = 1;
3812                 else
3813                   DCL_PTR_CONST (t->next) = 1;
3814               }
3815             t = t->next;
3816           }
3817       }
3818
3819 #if 0
3820       /* if the right is a literal replace the tree */
3821       if (IS_LITERAL (RETYPE (tree))) {
3822               if (!IS_PTR (LTYPE (tree))) {
3823                       tree->type = EX_VALUE;
3824                       tree->opval.val =
3825                               valCastLiteral (LTYPE (tree),
3826                                               floatFromVal (valFromType (RETYPE (tree))));
3827                       tree->left = NULL;
3828                       tree->right = NULL;
3829                       TTYPE (tree) = tree->opval.val->type;
3830                       tree->values.literalFromCast = 1;
3831               } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3832                          ((int)floatFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */  {
3833                       sym_link *rest = LTYPE(tree)->next;
3834                       werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3835                       TTYPE(tree) = newLink(DECLARATOR);
3836                       DCL_TYPE(TTYPE(tree)) = FPOINTER;
3837                       TTYPE(tree)->next = rest;
3838                       tree->left->opval.lnk = TTYPE(tree);
3839                       LRVAL (tree) = 1;
3840               } else {
3841                       TTYPE (tree) = LTYPE (tree);
3842                       LRVAL (tree) = 1;
3843               }
3844       } else {
3845               TTYPE (tree) = LTYPE (tree);
3846               LRVAL (tree) = 1;
3847       }
3848 #else
3849 #if 0 // this is already checked, now this could be explicit
3850       /* if pointer to struct then check names */
3851       if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3852           IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3853           strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3854         {
3855           werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3856                  SPEC_STRUCT(LETYPE(tree))->tag);
3857         }
3858 #endif
3859       if (IS_ADDRESS_OF_OP(tree->right)
3860           && IS_AST_SYM_VALUE (tree->right->left)
3861           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3862
3863         symbol * sym = AST_SYMBOL (tree->right->left);
3864         unsigned int gptype = 0;
3865         unsigned int addr = SPEC_ADDR (sym->etype);
3866
3867         if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3868                                         || TARGET_IS_PIC16) )
3869           {
3870             switch (SPEC_SCLS (sym->etype))
3871               {
3872               case S_CODE:
3873                 gptype = GPTYPE_CODE;
3874                 break;
3875               case S_XDATA:
3876                 gptype = GPTYPE_FAR;
3877                 break;
3878               case S_DATA:
3879               case S_IDATA:
3880                 gptype = GPTYPE_NEAR;
3881                 break;
3882               case S_PDATA:
3883                 gptype = GPTYPE_XSTACK;
3884                 break;
3885               default:
3886                 gptype = 0;
3887
3888                 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3889                     gptype = GPTYPE_NEAR;
3890               }
3891             addr |= gptype << (8*(GPTRSIZE - 1));
3892           }
3893
3894         tree->type = EX_VALUE;
3895         tree->opval.val =
3896           valCastLiteral (LTYPE (tree), addr);
3897         TTYPE (tree) = tree->opval.val->type;
3898         TETYPE (tree) = getSpec (TTYPE (tree));
3899         tree->left = NULL;
3900         tree->right = NULL;
3901         tree->values.literalFromCast = 1;
3902         return tree;
3903       }
3904
3905       /* handle offsetof macro:            */
3906       /* #define offsetof(TYPE, MEMBER) \  */
3907       /* ((unsigned) &((TYPE *)0)->MEMBER) */
3908       if (IS_ADDRESS_OF_OP(tree->right)
3909           && IS_AST_OP (tree->right->left)
3910           && tree->right->left->opval.op == PTR_OP
3911           && IS_AST_OP (tree->right->left->left)
3912           && tree->right->left->left->opval.op == CAST
3913           && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3914
3915         symbol *element = getStructElement (
3916           SPEC_STRUCT (LETYPE(tree->right->left)),
3917           AST_SYMBOL(tree->right->left->right)
3918         );
3919
3920         if (element) {
3921           tree->type = EX_VALUE;
3922           tree->opval.val = valCastLiteral (
3923             LTYPE (tree),
3924             element->offset
3925             + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3926           );
3927
3928           TTYPE (tree) = tree->opval.val->type;
3929           TETYPE (tree) = getSpec (TTYPE (tree));
3930           tree->left = NULL;
3931           tree->right = NULL;
3932           return tree;
3933         }
3934       }
3935
3936       /* if the right is a literal replace the tree */
3937       if (IS_LITERAL (RETYPE (tree))) {
3938         #if 0
3939         if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3940           /* rewrite      (type *)litaddr
3941              as           &temp
3942              and define   type at litaddr temp
3943              (but only if type's storage class is not generic)
3944           */
3945           ast *newTree = newNode ('&', NULL, NULL);
3946           symbol *sym;
3947
3948           TTYPE (newTree) = LTYPE (tree);
3949           TETYPE (newTree) = getSpec(LTYPE (tree));
3950
3951           /* define a global symbol at the casted address*/
3952           sym = newSymbol(genSymName (0), 0);
3953           sym->type = LTYPE (tree)->next;
3954           if (!sym->type)
3955             sym->type = newLink (V_VOID);
3956           sym->etype = getSpec(sym->type);
3957           SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3958           sym->lineDef = tree->lineno;
3959           sym->cdef = 1;
3960           sym->isref = 1;
3961           SPEC_STAT (sym->etype) = 1;
3962           SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3963           SPEC_ABSA(sym->etype) = 1;
3964           addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3965           allocGlobal (sym);
3966
3967           newTree->left = newAst_VALUE(symbolVal(sym));
3968           newTree->left->lineno = tree->lineno;
3969           LTYPE (newTree) = sym->type;
3970           LETYPE (newTree) = sym->etype;
3971           LLVAL (newTree) = 1;
3972           LRVAL (newTree) = 0;
3973           TLVAL (newTree) = 1;
3974           return newTree;
3975         }
3976         #endif
3977         if (!IS_PTR (LTYPE (tree))) {
3978           tree->type = EX_VALUE;
3979           tree->opval.val =
3980           valCastLiteral (LTYPE (tree),
3981                           floatFromVal (valFromType (RTYPE (tree))));
3982           TTYPE (tree) = tree->opval.val->type;
3983           tree->left = NULL;
3984           tree->right = NULL;
3985           tree->values.literalFromCast = 1;
3986           TETYPE (tree) = getSpec (TTYPE (tree));
3987           return tree;
3988         }
3989       }
3990       TTYPE (tree) = LTYPE (tree);
3991       LRVAL (tree) = 1;
3992
3993 #endif
3994       TETYPE (tree) = getSpec (TTYPE (tree));
3995
3996       return tree;
3997
3998       /*------------------------------------------------------------------*/
3999       /*----------------------------*/
4000       /*       logical &&, ||       */
4001       /*----------------------------*/
4002     case AND_OP:
4003     case OR_OP:
4004       /* each must be arithmetic type or be a pointer */
4005       if (!IS_PTR (LTYPE (tree)) &&
4006           !IS_ARRAY (LTYPE (tree)) &&
4007           !IS_INTEGRAL (LTYPE (tree)))
4008         {
4009           werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4010           goto errorTreeReturn;
4011         }
4012
4013       if (!IS_PTR (RTYPE (tree)) &&
4014           !IS_ARRAY (RTYPE (tree)) &&
4015           !IS_INTEGRAL (RTYPE (tree)))
4016         {
4017           werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4018           goto errorTreeReturn;
4019         }
4020       /* if they are both literal then */
4021       /* rewrite the tree */
4022       if (IS_LITERAL (RTYPE (tree)) &&
4023           IS_LITERAL (LTYPE (tree)))
4024         {
4025           tree->type = EX_VALUE;
4026           tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4027                                            valFromType (RTYPE (tree)),
4028                                            tree->opval.op);
4029           tree->right = tree->left = NULL;
4030           TETYPE (tree) = getSpec (TTYPE (tree) =
4031                                    tree->opval.val->type);
4032           return tree;
4033         }
4034       LRVAL (tree) = RRVAL (tree) = 1;
4035       TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4036       return tree;
4037
4038       /*------------------------------------------------------------------*/
4039       /*----------------------------*/
4040       /*     comparison operators   */
4041       /*----------------------------*/
4042     case '>':
4043     case '<':
4044     case LE_OP:
4045     case GE_OP:
4046     case EQ_OP:
4047     case NE_OP:
4048       {
4049         ast *lt = optimizeCompare (tree);
4050
4051         if (tree != lt)
4052           return lt;
4053       }
4054
4055       /* if they are pointers they must be castable */
4056       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4057         {
4058           if (tree->opval.op==EQ_OP &&
4059               !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4060             // we cannot cast a gptr to a !gptr: switch the leaves
4061             struct ast *s=tree->left;
4062             tree->left=tree->right;
4063             tree->right=s;
4064           }
4065           if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4066             {
4067               werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4068               fprintf (stderr, "comparing type ");
4069               printTypeChain (LTYPE (tree), stderr);
4070               fprintf (stderr, "to type ");
4071               printTypeChain (RTYPE (tree), stderr);
4072               fprintf (stderr, "\n");
4073               goto errorTreeReturn;
4074             }
4075         }
4076       /* else they should be promotable to one another */
4077       else
4078         {
4079           if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4080                 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4081
4082             if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4083               {
4084                 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4085                 fprintf (stderr, "comparing type ");
4086                 printTypeChain (LTYPE (tree), stderr);
4087                 fprintf (stderr, "to type ");
4088                 printTypeChain (RTYPE (tree), stderr);
4089                 fprintf (stderr, "\n");
4090                 goto errorTreeReturn;
4091               }
4092         }
4093
4094       {
4095         CCR_RESULT ccr_result = CCR_OK;
4096
4097         /* if left is integral and right is literal
4098            then check constant range */
4099         if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4100           ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4101                                            tree->opval.op, FALSE);
4102         if (ccr_result == CCR_OK &&
4103             IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4104           ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4105                                            tree->opval.op, TRUE);
4106         switch (ccr_result)
4107             {
4108               case CCR_ALWAYS_TRUE:
4109               case CCR_ALWAYS_FALSE:
4110                 if (!options.lessPedantic)
4111                   werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4112                           ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4113                 return decorateType (newAst_VALUE (constVal (
4114                                    ccr_result == CCR_ALWAYS_TRUE ? "1" : "0")),
4115                                                    resultType);
4116               case CCR_OK:
4117               default:
4118                 break;
4119             }
4120       }
4121
4122       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4123       if (tree->opval.op == '>' &&
4124           SPEC_USIGN(LETYPE(tree)) &&
4125           IS_LITERAL(RTYPE(tree))  &&
4126           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
4127         {
4128           if (resultType == RESULT_TYPE_IFX)
4129             {
4130               /* the parent is an ifx: */
4131               /* if (unsigned value) */
4132               return tree->left;
4133             }
4134
4135           /* (unsigned value) ? 1 : 0 */
4136           tree->opval.op = '?';
4137           tree->right = newNode (':',
4138                                   newAst_VALUE (constVal ("1")),
4139                                   tree->right); /* val 0 */
4140           tree->right->lineno = tree->lineno;
4141           tree->right->left->lineno = tree->lineno;
4142           tree->decorated = 0;
4143           return decorateType (tree, resultType);
4144         }
4145
4146       /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4147       if (IS_LITERAL(RTYPE(tree))  &&
4148           floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4149           tree->opval.op == EQ_OP &&
4150           resultType == RESULT_TYPE_IFX)
4151         {
4152           tree->opval.op = '!';
4153           tree->right = NULL;
4154           tree->decorated = 0;
4155           return decorateType (tree, resultType);
4156         }
4157
4158       /* if they are both literal then */
4159       /* rewrite the tree */
4160       if (IS_LITERAL (RTYPE (tree)) &&
4161           IS_LITERAL (LTYPE (tree)))
4162         {
4163           tree->type = EX_VALUE;
4164           tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4165                                         valFromType (RETYPE (tree)),
4166                                         tree->opval.op);
4167           tree->right = tree->left = NULL;
4168           TETYPE (tree) = getSpec (TTYPE (tree) =
4169                                    tree->opval.val->type);
4170           return tree;
4171         }
4172
4173       /* if one is 'signed char ' and the other one is 'unsigned char' */
4174       /* it's necessary to promote to int */
4175       if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4176           (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4177         {
4178           /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4179              if it's possible to use a 'signed char' */
4180
4181               /* is left a 'unsigned char'? */
4182           if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4183               /* the value range of a 'unsigned char' is 0...255;
4184                  if the actual value is < 128 it can be changed to signed */
4185               (int) floatFromVal (valFromType (RETYPE (tree))) < 128)
4186             {
4187               /* now we've got 2 'signed char'! */
4188               SPEC_USIGN (RETYPE (tree)) = 0;
4189             }
4190                    /* same test for the left operand: */
4191           else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4192               (int) floatFromVal (valFromType (LETYPE (tree))) < 128)
4193             {
4194               SPEC_USIGN (LETYPE (tree)) = 0;
4195             }
4196           else
4197             {
4198               werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4199               tree->left  = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4200               tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4201             }
4202         }
4203
4204       LRVAL (tree) = RRVAL (tree) = 1;
4205       TTYPE (tree) = TETYPE (tree) = newBoolLink ();
4206
4207       /* condition transformations */
4208       {
4209         unsigned transformedOp = 0;
4210
4211         switch (tree->opval.op)
4212           {
4213             case '<':             /* transform (a < b)  to !(a >= b)  */
4214               if (port->lt_nge)
4215                 transformedOp = GE_OP;
4216               break;
4217             case '>':             /* transform (a > b)  to !(a <= b)  */
4218               if (port->gt_nle)
4219                 transformedOp = LE_OP;
4220               break;
4221             case LE_OP:           /* transform (a <= b) to !(a > b)   */
4222               if (port->le_ngt)
4223                 transformedOp = '>';
4224               break;
4225             case GE_OP:           /* transform (a >= b) to !(a < b)   */
4226               if (port->ge_nlt)
4227                 transformedOp = '<';
4228               break;
4229             case NE_OP:           /* transform (a != b) to !(a == b)   */
4230               if (port->ne_neq)
4231                 transformedOp = EQ_OP;
4232               break;
4233             case EQ_OP:           /* transform (a == b) to !(a != b)   */
4234               if (port->eq_nne)
4235                 transformedOp = NE_OP;
4236               break;
4237             default:
4238               break;
4239           }
4240         if (transformedOp)
4241           {
4242             tree->opval.op = transformedOp;
4243             tree->decorated = 0;
4244             tree = newNode ('!', tree, NULL);
4245             tree->lineno = tree->left->lineno;
4246             return decorateType (tree, resultType);
4247           }
4248       }
4249
4250       return tree;
4251
4252       /*------------------------------------------------------------------*/
4253       /*----------------------------*/
4254       /*             sizeof         */
4255       /*----------------------------*/
4256     case SIZEOF:                /* evaluate wihout code generation */
4257       /* change the type to a integer */
4258       {
4259         int size = getSize (tree->right->ftype);
4260         SNPRINTF(buffer, sizeof(buffer), "%d", size);
4261         if (!size && !IS_VOID(tree->right->ftype))
4262           werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4263       }
4264       tree->type = EX_VALUE;
4265       tree->opval.val = constVal (buffer);
4266       tree->right = tree->left = NULL;
4267       TETYPE (tree) = getSpec (TTYPE (tree) =
4268                                tree->opval.val->type);
4269       return tree;
4270
4271       /*------------------------------------------------------------------*/
4272       /*----------------------------*/
4273       /*             typeof         */
4274       /*----------------------------*/
4275     case TYPEOF:
4276         /* return typeof enum value */
4277         tree->type = EX_VALUE;
4278         {
4279             int typeofv = 0;
4280             if (IS_SPEC(tree->right->ftype)) {
4281                 switch (SPEC_NOUN(tree->right->ftype)) {
4282                 case V_INT:
4283                     if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4284                     else typeofv = TYPEOF_INT;
4285                     break;
4286                 case V_FLOAT:
4287                     typeofv = TYPEOF_FLOAT;
4288                     break;
4289                 case V_FIXED16X16:
4290                     typeofv = TYPEOF_FIXED16X16;
4291                     break;
4292                 case V_CHAR:
4293                     typeofv = TYPEOF_CHAR;
4294                     break;
4295                 case V_VOID:
4296                     typeofv = TYPEOF_VOID;
4297                     break;
4298                 case V_STRUCT:
4299                     typeofv = TYPEOF_STRUCT;
4300                     break;
4301                 case V_BITFIELD:
4302                     typeofv = TYPEOF_BITFIELD;
4303                     break;
4304                 case V_BIT:
4305                     typeofv = TYPEOF_BIT;
4306                     break;
4307                 case V_SBIT:
4308                     typeofv = TYPEOF_SBIT;
4309                     break;
4310                 default:
4311                     break;
4312                 }
4313             } else {
4314                 switch (DCL_TYPE(tree->right->ftype)) {
4315                 case POINTER:
4316                     typeofv = TYPEOF_POINTER;
4317                     break;
4318                 case FPOINTER:
4319                     typeofv = TYPEOF_FPOINTER;
4320                     break;
4321                 case CPOINTER:
4322                     typeofv = TYPEOF_CPOINTER;
4323                     break;
4324                 case GPOINTER:
4325                     typeofv = TYPEOF_GPOINTER;
4326                     break;
4327                 case PPOINTER:
4328                     typeofv = TYPEOF_PPOINTER;
4329                     break;
4330                 case IPOINTER:
4331                     typeofv = TYPEOF_IPOINTER;
4332                     break;
4333                 case ARRAY:
4334                     typeofv = TYPEOF_ARRAY;
4335                     break;
4336                 case FUNCTION:
4337                     typeofv = TYPEOF_FUNCTION;
4338                     break;
4339                 default:
4340                     break;
4341                 }
4342             }
4343             SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4344             tree->opval.val = constVal (buffer);
4345             tree->right = tree->left = NULL;
4346             TETYPE (tree) = getSpec (TTYPE (tree) =
4347                                      tree->opval.val->type);
4348         }
4349         return tree;
4350       /*------------------------------------------------------------------*/
4351       /*----------------------------*/
4352       /* conditional operator  '?'  */
4353       /*----------------------------*/
4354     case '?':
4355       /* the type is value of the colon operator (on the right) */
4356       assert (IS_COLON_OP (tree->right));
4357       /* if already known then replace the tree : optimizer will do it
4358          but faster to do it here */
4359       if (IS_LITERAL (LTYPE (tree)))
4360         {
4361           if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0)
4362             return decorateType (tree->right->left, resultTypeProp);
4363           else
4364             return decorateType (tree->right->right, resultTypeProp);
4365         }
4366       else
4367         {
4368           tree->right = decorateType (tree->right, resultTypeProp);
4369           TTYPE (tree) = RTYPE (tree);
4370           TETYPE (tree) = getSpec (TTYPE (tree));
4371         }
4372       return tree;
4373
4374     case ':':
4375       /* if they don't match we have a problem */
4376       if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4377           (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4378         {
4379           werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4380           goto errorTreeReturn;
4381         }
4382
4383       TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4384                                   resultType, tree->opval.op);
4385       TETYPE (tree) = getSpec (TTYPE (tree));
4386       return tree;
4387
4388
4389 #if 0 // assignment operators are converted by the parser
4390       /*------------------------------------------------------------------*/
4391       /*----------------------------*/
4392       /*    assignment operators    */
4393       /*----------------------------*/
4394     case MUL_ASSIGN:
4395     case DIV_ASSIGN:
4396       /* for these it must be both must be integral */
4397       if (!IS_ARITHMETIC (LTYPE (tree)) ||
4398           !IS_ARITHMETIC (RTYPE (tree)))
4399         {
4400           werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4401           goto errorTreeReturn;
4402         }
4403       RRVAL (tree) = 1;
4404       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4405
4406       if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4407         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4408
4409       if (LRVAL (tree))
4410         {
4411           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4412           goto errorTreeReturn;
4413         }
4414       LLVAL (tree) = 1;
4415
4416       return tree;
4417
4418     case AND_ASSIGN:
4419     case OR_ASSIGN:
4420     case XOR_ASSIGN:
4421     case RIGHT_ASSIGN:
4422     case LEFT_ASSIGN:
4423       /* for these it must be both must be integral */
4424       if (!IS_INTEGRAL (LTYPE (tree)) ||
4425           !IS_INTEGRAL (RTYPE (tree)))
4426         {
4427           werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4428           goto errorTreeReturn;
4429         }
4430       RRVAL (tree) = 1;
4431       TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4432
4433       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4434         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4435
4436       if (LRVAL (tree))
4437         {
4438           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4439           goto errorTreeReturn;
4440         }
4441       LLVAL (tree) = 1;
4442
4443       return tree;
4444
4445       /*------------------------------------------------------------------*/
4446       /*----------------------------*/
4447       /*    -= operator             */
4448       /*----------------------------*/
4449     case SUB_ASSIGN:
4450       if (!(IS_PTR (LTYPE (tree)) ||
4451             IS_ARITHMETIC (LTYPE (tree))))
4452         {
4453           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4454           goto errorTreeReturn;
4455         }
4456
4457       if (!(IS_PTR (RTYPE (tree)) ||
4458             IS_ARITHMETIC (RTYPE (tree))))
4459         {
4460           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4461           goto errorTreeReturn;
4462         }
4463       RRVAL (tree) = 1;
4464       TETYPE (tree) = getSpec (TTYPE (tree) =
4465                                computeType (LTYPE (tree),
4466                                             RTYPE (tree),
4467                                             RESULT_TYPE_NOPROM,
4468                                             tree->opval.op));
4469
4470       if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4471         werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4472
4473       if (LRVAL (tree))
4474         {
4475           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4476           goto errorTreeReturn;
4477         }
4478       LLVAL (tree) = 1;
4479
4480       return tree;
4481
4482       /*------------------------------------------------------------------*/
4483       /*----------------------------*/
4484       /*          += operator       */
4485       /*----------------------------*/
4486     case ADD_ASSIGN:
4487       /* this is not a unary operation */
4488       /* if both pointers then problem */
4489       if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4490         {
4491           werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4492           goto errorTreeReturn;
4493         }
4494
4495       if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4496         {
4497           werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4498           goto errorTreeReturn;
4499         }
4500
4501       if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (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
4522       tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4523       tree->opval.op = '=';
4524
4525       return tree;
4526 #endif
4527
4528       /*------------------------------------------------------------------*/
4529       /*----------------------------*/
4530       /*      straight assignemnt   */
4531       /*----------------------------*/
4532     case '=':
4533       /* cannot be an aggregate */
4534       if (IS_AGGREGATE (LTYPE (tree)))
4535         {
4536           werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4537           goto errorTreeReturn;
4538         }
4539
4540       /* they should either match or be castable */
4541       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4542         {
4543           werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4544           printFromToType(RTYPE(tree),LTYPE(tree));
4545         }
4546
4547       /* if the left side of the tree is of type void
4548          then report error */
4549       if (IS_VOID (LTYPE (tree)))
4550         {
4551           werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4552           printFromToType(RTYPE(tree), LTYPE(tree));
4553         }
4554
4555       TETYPE (tree) = getSpec (TTYPE (tree) =
4556                                LTYPE (tree));
4557       RRVAL (tree) = 1;
4558       LLVAL (tree) = 1;
4559       if (!tree->initMode ) {
4560         if (IS_CONSTANT(LTYPE(tree)))
4561           werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4562       }
4563       if (LRVAL (tree))
4564         {
4565           werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4566           goto errorTreeReturn;
4567         }
4568
4569       return tree;
4570
4571       /*------------------------------------------------------------------*/
4572       /*----------------------------*/
4573       /*      comma operator        */
4574       /*----------------------------*/
4575     case ',':
4576       TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4577       return tree;
4578
4579       /*------------------------------------------------------------------*/
4580       /*----------------------------*/
4581       /*       function call        */
4582       /*----------------------------*/
4583     case CALL:
4584
4585       /* undo any explicit pointer derefernce; PCALL will handle it instead */
4586       if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4587         {
4588           if (tree->left->opval.op == '*' && !tree->left->right)
4589             tree->left = tree->left->left;
4590         }
4591
4592       /* require a function or pointer to function */
4593       if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4594         {
4595           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4596           goto errorTreeReturn;
4597         }
4598
4599       /* if there are parms, make sure that
4600          parms are decorate / process / reverse only once */
4601       if (!tree->right ||
4602           !tree->right->decorated)
4603         {
4604           sym_link *functype;
4605           parmNumber = 1;
4606
4607           if (IS_FUNCPTR (LTYPE (tree)))
4608             {
4609               functype = LTYPE (tree)->next;
4610               processFuncPtrArgs (functype);
4611             }
4612           else
4613             functype = LTYPE (tree);
4614
4615           if (processParms (tree->left, FUNC_ARGS(functype),
4616                             &tree->right, &parmNumber, TRUE))
4617             {
4618               goto errorTreeReturn;
4619             }
4620
4621           if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4622              !IFFUNC_ISBUILTIN(functype))
4623             {
4624               reverseParms (tree->right);
4625             }
4626
4627            TTYPE (tree) = functype->next;
4628            TETYPE (tree) = getSpec (TTYPE (tree));
4629         }
4630       return tree;
4631
4632       /*------------------------------------------------------------------*/
4633       /*----------------------------*/
4634       /*     return statement       */
4635       /*----------------------------*/
4636     case RETURN:
4637       if (!tree->right)
4638         goto voidcheck;
4639
4640       if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4641         {
4642           werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4643           printFromToType (RTYPE(tree), currFunc->type->next);
4644           goto errorTreeReturn;
4645         }
4646
4647       if (IS_VOID (currFunc->type->next)
4648           && tree->right &&
4649           !IS_VOID (RTYPE (tree)))
4650         {
4651           werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4652           goto errorTreeReturn;
4653         }
4654
4655       /* if there is going to be a casting required then add it */
4656       if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4657         {
4658           tree->right =
4659             decorateType (newNode (CAST,
4660                           newAst_LINK (copyLinkChain (currFunc->type->next)),
4661                                         tree->right),
4662                           RESULT_TYPE_NONE);
4663         }
4664
4665       RRVAL (tree) = 1;
4666       return tree;
4667
4668     voidcheck:
4669
4670       if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4671         {
4672           werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4673           goto errorTreeReturn;
4674         }
4675
4676       TTYPE (tree) = TETYPE (tree) = NULL;
4677       return tree;
4678
4679       /*------------------------------------------------------------------*/
4680       /*----------------------------*/
4681       /*     switch statement       */
4682       /*----------------------------*/
4683     case SWITCH:
4684       /* the switch value must be an integer */
4685       if (!IS_INTEGRAL (LTYPE (tree)))
4686         {
4687           werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4688           goto errorTreeReturn;
4689         }
4690       LRVAL (tree) = 1;
4691       TTYPE (tree) = TETYPE (tree) = NULL;
4692       return tree;
4693
4694       /*------------------------------------------------------------------*/
4695       /*----------------------------*/
4696       /* ifx Statement              */
4697       /*----------------------------*/
4698     case IFX:
4699       tree->left = backPatchLabels (tree->left,
4700                                     tree->trueLabel,
4701                                     tree->falseLabel);
4702       TTYPE (tree) = TETYPE (tree) = NULL;
4703       return tree;
4704
4705       /*------------------------------------------------------------------*/
4706       /*----------------------------*/
4707       /* for Statement              */
4708       /*----------------------------*/
4709     case FOR:
4710
4711       AST_FOR (tree, initExpr) = decorateType (
4712                   resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4713       AST_FOR (tree, condExpr) = decorateType (
4714                   resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4715       AST_FOR (tree, loopExpr) = decorateType (
4716                   resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4717
4718       /* if the for loop is reversible then
4719          reverse it otherwise do what we normally
4720          do */
4721       {
4722         symbol *sym;
4723         ast *init, *end;
4724
4725         if (isLoopReversible (tree, &sym, &init, &end))
4726           return reverseLoop (tree, sym, init, end);
4727         else
4728           return decorateType (createFor (AST_FOR (tree, trueLabel),
4729                                           AST_FOR (tree, continueLabel),
4730                                           AST_FOR (tree, falseLabel),
4731                                           AST_FOR (tree, condLabel),
4732                                           AST_FOR (tree, initExpr),
4733                                           AST_FOR (tree, condExpr),
4734                                           AST_FOR (tree, loopExpr),
4735                                           tree->left), RESULT_TYPE_NONE);
4736       }
4737     case PARAM:
4738       werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4739               "node PARAM shouldn't be processed here");
4740               /* but in processParams() */
4741       return tree;
4742     default:
4743       TTYPE (tree) = TETYPE (tree) = NULL;
4744       return tree;
4745     }
4746
4747   /* some error found this tree will be killed */
4748 errorTreeReturn:
4749   TTYPE (tree) = TETYPE (tree) = newCharLink ();
4750   tree->opval.op = NULLOP;
4751   tree->isError = 1;
4752
4753   return tree;
4754 }
4755
4756 /*-----------------------------------------------------------------*/
4757 /* sizeofOp - processes size of operation                          */
4758 /*-----------------------------------------------------------------*/
4759 value *
4760 sizeofOp (sym_link * type)
4761 {
4762   char buff[10];
4763   int size;
4764
4765   /* make sure the type is complete and sane */
4766   checkTypeSanity(type, "(sizeof)");
4767
4768   /* get the size and convert it to character  */
4769   SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4770   if (!size && !IS_VOID(type))
4771     werror (E_SIZEOF_INCOMPLETE_TYPE);
4772
4773   /* now convert into value  */
4774   return constVal (buff);
4775 }
4776
4777
4778 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4779 #define IS_OR(ex)  (ex->type == EX_OP && ex->opval.op == OR_OP )
4780 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4781 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4782 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4783 #define IS_LT(ex)  (ex->type == EX_OP && ex->opval.op == '<' )
4784 #define IS_GT(ex)  (ex->type == EX_OP && ex->opval.op == '>')
4785
4786 /*-----------------------------------------------------------------*/
4787 /* backPatchLabels - change and or not operators to flow control    */
4788 /*-----------------------------------------------------------------*/
4789 static ast *
4790 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4791 {
4792
4793   if (!tree)
4794     return NULL;
4795
4796   /* while-loops insert a label between the IFX and the condition,
4797      therefore look behind the label too */
4798   if (tree->opval.op == LABEL &&
4799       tree->right &&
4800       IS_ANDORNOT (tree->right))
4801     {
4802       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4803       return tree;
4804     }
4805
4806   if (!(IS_ANDORNOT (tree)))
4807     return tree;
4808
4809   /* if this an and */
4810   if (IS_AND (tree))
4811     {
4812       static int localLbl = 0;
4813       symbol *localLabel;
4814
4815       SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4816       localLabel = newSymbol (buffer, NestLevel);
4817
4818       tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4819
4820       /* if left is already a IFX then just change the if true label in that */
4821       if (!IS_IFX (tree->left))
4822         tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4823
4824       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4825       /* right is a IFX then just join */
4826       if (IS_IFX (tree->right))
4827         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4828
4829       tree->right = createLabel (localLabel, tree->right);
4830       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4831
4832       return newNode (NULLOP, tree->left, tree->right);
4833     }
4834
4835   /* if this is an or operation */
4836   if (IS_OR (tree))
4837     {
4838       static int localLbl = 0;
4839       symbol *localLabel;
4840
4841       SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4842       localLabel = newSymbol (buffer, NestLevel);
4843
4844       tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4845
4846       /* if left is already a IFX then just change the if true label in that */
4847       if (!IS_IFX (tree->left))
4848         tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4849
4850       tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4851       /* right is a IFX then just join */
4852       if (IS_IFX (tree->right))
4853         return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4854
4855       tree->right = createLabel (localLabel, tree->right);
4856       tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4857
4858       return newNode (NULLOP, tree->left, tree->right);
4859     }
4860
4861   /* change not */
4862   if (IS_NOT (tree))
4863     {
4864       /* call with exchanged labels */
4865       tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4866
4867       /* if left isn't already a IFX */
4868       if (!IS_IFX (tree->left))
4869         {
4870           tree->left = newNode (IFX, tree->left, NULL);
4871           tree->left->trueLabel = falseLabel;
4872           tree->left->falseLabel = trueLabel;
4873         }
4874       return tree->left;
4875      }
4876
4877   if (IS_IFX (tree))
4878     {
4879       tree->trueLabel = trueLabel;
4880       tree->falseLabel = falseLabel;
4881     }
4882
4883   return tree;
4884 }
4885
4886
4887 /*-----------------------------------------------------------------*/
4888 /* createBlock - create expression tree for block                  */
4889 /*-----------------------------------------------------------------*/
4890 ast *
4891 createBlock (symbol * decl, ast * body)
4892 {
4893   ast *ex;
4894
4895   /* if the block has nothing */
4896   if (!body && !decl)
4897     return NULL;
4898
4899   ex = newNode (BLOCK, NULL, body);
4900   ex->values.sym = decl;
4901
4902   ex->level++;
4903   ex->lineno = 0;
4904   return ex;
4905 }
4906
4907 /*-----------------------------------------------------------------*/
4908 /* createLabel - creates the expression tree for labels            */
4909 /*-----------------------------------------------------------------*/
4910 ast *
4911 createLabel (symbol * label, ast * stmnt)
4912 {
4913   symbol *csym;
4914   char name[SDCC_NAME_MAX + 1];
4915   ast *rValue;
4916
4917   /* must create fresh symbol if the symbol name  */
4918   /* exists in the symbol table, since there can  */
4919   /* be a variable with the same name as the labl */
4920   if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4921       (csym->level == label->level))
4922     label = newSymbol (label->name, label->level);
4923
4924   /* change the name before putting it in add _ */
4925   SNPRINTF(name, sizeof(name), "%s", label->name);
4926
4927   /* put the label in the LabelSymbol table    */
4928   /* but first check if a label of the same    */
4929   /* name exists                               */
4930   if ((csym = findSym (LabelTab, NULL, name)))
4931     werror (E_DUPLICATE_LABEL, label->name);
4932   else
4933     addSym (LabelTab, label, name, label->level, 0, 0);
4934
4935   label->isitmp = 1;
4936   label->islbl = 1;
4937   label->key = labelKey++;
4938   rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4939   rValue->lineno = 0;
4940
4941   return rValue;
4942 }
4943
4944 /*-----------------------------------------------------------------*/
4945 /* createCase - generates the parsetree for a case statement       */
4946 /*-----------------------------------------------------------------*/
4947 ast *
4948 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4949 {
4950   char caseLbl[SDCC_NAME_MAX + 1];
4951   ast *rexpr;
4952   value *val;
4953
4954   /* if the switch statement does not exist */
4955   /* then case is out of context            */
4956   if (!swStat)
4957     {
4958       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
4959       return NULL;
4960     }
4961
4962   caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
4963   /* if not a constant then error  */
4964   if (!IS_LITERAL (caseVal->ftype))
4965     {
4966       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
4967       return NULL;
4968     }
4969
4970   /* if not a integer than error */
4971   if (!IS_INTEGRAL (caseVal->ftype))
4972     {
4973       werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
4974       return NULL;
4975     }
4976
4977   /* find the end of the switch values chain   */
4978   if (!(val = swStat->values.switchVals.swVals))
4979     swStat->values.switchVals.swVals = caseVal->opval.val;
4980   else
4981     {
4982       /* also order the cases according to value */
4983       value *pval = NULL;
4984       int cVal = (int) floatFromVal (caseVal->opval.val);
4985       while (val && (int) floatFromVal (val) < cVal)
4986         {
4987           pval = val;
4988           val = val->next;
4989         }
4990
4991       /* if we reached the end then */
4992       if (!val)
4993         {
4994           pval->next = caseVal->opval.val;
4995         }
4996       else if ((int) floatFromVal (val) == cVal)
4997         {
4998           werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
4999                     "case");
5000           return NULL;
5001         }
5002       else
5003         {
5004           /* we found a value greater than */
5005           /* the current value we must add this */
5006           /* before the value */
5007           caseVal->opval.val->next = val;
5008
5009           /* if this was the first in chain */
5010           if (swStat->values.switchVals.swVals == val)
5011             swStat->values.switchVals.swVals =
5012               caseVal->opval.val;
5013           else
5014             pval->next = caseVal->opval.val;
5015         }
5016
5017     }
5018
5019   /* create the case label   */
5020   SNPRINTF(caseLbl, sizeof(caseLbl),
5021            "_case_%d_%d",
5022            swStat->values.switchVals.swNum,
5023            (int) floatFromVal (caseVal->opval.val));
5024
5025   rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5026   rexpr->lineno = 0;
5027   return rexpr;
5028 }
5029
5030 /*-----------------------------------------------------------------*/
5031 /* createDefault - creates the parse tree for the default statement */
5032 /*-----------------------------------------------------------------*/
5033 ast *
5034 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5035 {
5036   char defLbl[SDCC_NAME_MAX + 1];
5037
5038   /* if the switch statement does not exist */
5039   /* then case is out of context            */
5040   if (!swStat)
5041     {
5042       werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5043       return NULL;
5044     }
5045
5046   if (swStat->values.switchVals.swDefault)
5047     {
5048       werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5049                 "default");
5050       return NULL;
5051     }
5052
5053   /* turn on the default flag   */
5054   swStat->values.switchVals.swDefault = 1;
5055
5056   /* create the label  */
5057   SNPRINTF (defLbl, sizeof(defLbl),
5058             "_default_%d", swStat->values.switchVals.swNum);
5059   return createLabel (newSymbol (defLbl, 0), stmnt);
5060 }
5061
5062 /*-----------------------------------------------------------------*/
5063 /* createIf - creates the parsetree for the if statement           */
5064 /*-----------------------------------------------------------------*/
5065 ast *
5066 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5067 {
5068   static int Lblnum = 0;
5069   ast *ifTree;
5070   symbol *ifTrue, *ifFalse, *ifEnd;
5071
5072   /* if neither exists */
5073   if (!elseBody && !ifBody) {
5074     // if there are no side effects (i++, j() etc)
5075     if (!hasSEFcalls(condAst)) {
5076       return condAst;
5077     }
5078   }
5079
5080   /* create the labels */
5081   SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5082   ifFalse = newSymbol (buffer, NestLevel);
5083   /* if no else body then end == false */
5084   if (!elseBody)
5085     ifEnd = ifFalse;
5086   else
5087     {
5088       SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5089       ifEnd = newSymbol (buffer, NestLevel);
5090     }
5091
5092   SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5093   ifTrue = newSymbol (buffer, NestLevel);
5094
5095   Lblnum++;
5096
5097   /* attach the ifTrue label to the top of it body */
5098   ifBody = createLabel (ifTrue, ifBody);
5099   /* attach a goto end to the ifBody if else is present */
5100   if (elseBody)
5101     {
5102       ifBody = newNode (NULLOP, ifBody,
5103                         newNode (GOTO,
5104                                  newAst_VALUE (symbolVal (ifEnd)),
5105                                  NULL));
5106       /* put the elseLabel on the else body */
5107       elseBody = createLabel (ifFalse, elseBody);
5108       /* out the end at the end of the body */
5109       elseBody = newNode (NULLOP,
5110                           elseBody,
5111                           createLabel (ifEnd, NULL));
5112     }
5113   else
5114     {
5115       ifBody = newNode (NULLOP, ifBody,
5116                         createLabel (ifFalse, NULL));
5117     }
5118   condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5119   if (IS_IFX (condAst))
5120     ifTree = condAst;
5121   else
5122     ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5123
5124   return newNode (NULLOP, ifTree,
5125                   newNode (NULLOP, ifBody, elseBody));
5126
5127 }
5128
5129 /*-----------------------------------------------------------------*/
5130 /* createDo - creates parse tree for do                            */
5131 /*        _dobody_n:                                               */
5132 /*            statements                                           */
5133 /*        _docontinue_n:                                           */
5134 /*            condition_expression +-> trueLabel -> _dobody_n      */
5135 /*                                 |                               */
5136 /*                                 +-> falseLabel-> _dobreak_n     */
5137 /*        _dobreak_n:                                              */
5138 /*-----------------------------------------------------------------*/
5139 ast *
5140 createDo (symbol * trueLabel, symbol * continueLabel,
5141           symbol * falseLabel, ast * condAst, ast * doBody)
5142 {
5143   ast *doTree;
5144
5145
5146   /* if the body does not exist then it is simple */
5147   if (!doBody)
5148     {
5149       condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5150       doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5151                 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5152       doTree->trueLabel = continueLabel;
5153       doTree->falseLabel = NULL;
5154
5155       doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5156       return doTree;
5157     }
5158
5159   /* otherwise we have a body */
5160   condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5161
5162   /* attach the body label to the top */
5163   doBody = createLabel (trueLabel, doBody);
5164   /* attach the continue label to end of body */
5165   doBody = newNode (NULLOP, doBody,
5166                     createLabel (continueLabel, NULL));
5167
5168   /* now put the break label at the end */
5169   if (IS_IFX (condAst))
5170     doTree = condAst;
5171   else
5172     doTree = newIfxNode (condAst, trueLabel, falseLabel);
5173
5174   doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5175
5176   /* putting it together */
5177   return newNode (NULLOP, doBody, doTree);
5178 }
5179
5180 /*-----------------------------------------------------------------*/
5181 /* createFor - creates parse tree for 'for' statement              */
5182 /*        initExpr                                                 */
5183 /*   _forcond_n:                                                   */
5184 /*        condExpr  +-> trueLabel -> _forbody_n                    */
5185 /*                  |                                              */
5186 /*                  +-> falseLabel-> _forbreak_n                   */
5187 /*   _forbody_n:                                                   */
5188 /*        statements                                               */
5189 /*   _forcontinue_n:                                               */
5190 /*        loopExpr                                                 */
5191 /*        goto _forcond_n ;                                        */
5192 /*   _forbreak_n:                                                  */
5193 /*-----------------------------------------------------------------*/
5194 ast *
5195 createFor (symbol * trueLabel, symbol * continueLabel,
5196            symbol * falseLabel, symbol * condLabel,
5197            ast * initExpr, ast * condExpr, ast * loopExpr,
5198            ast * forBody)
5199 {
5200   ast *forTree;
5201
5202   /* if loopexpression not present then we can generate it */
5203   /* the same way as a while */
5204   if (!loopExpr)
5205     return newNode (NULLOP, initExpr,
5206                     createWhile (trueLabel, continueLabel,
5207                                  falseLabel, condExpr, forBody));
5208   /* vanilla for statement */
5209   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5210
5211   if (condExpr && !IS_IFX (condExpr))
5212     condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5213
5214
5215   /* attach condition label to condition */
5216   condExpr = createLabel (condLabel, condExpr);
5217
5218   /* attach body label to body */
5219   forBody = createLabel (trueLabel, forBody);
5220
5221   /* attach continue to forLoop expression & attach */
5222   /* goto the forcond @ and of loopExpression       */
5223   loopExpr = createLabel (continueLabel,
5224                           newNode (NULLOP,
5225                                    loopExpr,
5226                                    newNode (GOTO,
5227                                        newAst_VALUE (symbolVal (condLabel)),
5228                                             NULL)));
5229   /* now start putting them together */
5230   forTree = newNode (NULLOP, initExpr, condExpr);
5231   forTree = newNode (NULLOP, forTree, forBody);
5232   forTree = newNode (NULLOP, forTree, loopExpr);
5233   /* finally add the break label */
5234   forTree = newNode (NULLOP, forTree,
5235                      createLabel (falseLabel, NULL));
5236   return forTree;
5237 }
5238
5239 /*-----------------------------------------------------------------*/
5240 /* createWhile - creates parse tree for while statement            */
5241 /*               the while statement will be created as follows    */
5242 /*                                                                 */
5243 /*      _while_continue_n:                                         */
5244 /*            condition_expression +-> trueLabel -> _while_boby_n  */
5245 /*                                 |                               */
5246 /*                                 +-> falseLabel -> _while_break_n */
5247 /*      _while_body_n:                                             */
5248 /*            statements                                           */
5249 /*            goto _while_continue_n                               */
5250 /*      _while_break_n:                                            */
5251 /*-----------------------------------------------------------------*/
5252 ast *
5253 createWhile (symbol * trueLabel, symbol * continueLabel,
5254              symbol * falseLabel, ast * condExpr, ast * whileBody)
5255 {
5256   ast *whileTree;
5257
5258   /* put the continue label */
5259   condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5260   condExpr = createLabel (continueLabel, condExpr);
5261   condExpr->lineno = 0;
5262
5263   /* put the body label in front of the body */
5264   whileBody = createLabel (trueLabel, whileBody);
5265   whileBody->lineno = 0;
5266   /* put a jump to continue at the end of the body */
5267   /* and put break label at the end of the body */
5268   whileBody = newNode (NULLOP,
5269                        whileBody,
5270                        newNode (GOTO,
5271                                 newAst_VALUE (symbolVal (continueLabel)),
5272                                 createLabel (falseLabel, NULL)));
5273
5274   /* put it all together */
5275   if (IS_IFX (condExpr))
5276     whileTree = condExpr;
5277   else
5278     {
5279       whileTree = newNode (IFX, condExpr, NULL);
5280       /* put the true & false labels in place */
5281       whileTree->trueLabel = trueLabel;
5282       whileTree->falseLabel = falseLabel;
5283     }
5284
5285   return newNode (NULLOP, whileTree, whileBody);
5286 }
5287
5288 /*-----------------------------------------------------------------*/
5289 /* isShiftRightLitVal _BitAndLitVal - helper function              */
5290 /*-----------------------------------------------------------------*/
5291 static ast *
5292 isShiftRightLitVal_BitAndLitVal (ast * tree)
5293 {
5294   /* if this is not a bit and */
5295   if (!IS_BITAND (tree))
5296     return NULL;
5297
5298   /* will look for tree of the form
5299      ( expr >> litval2) & litval1 */
5300   if (!IS_AST_LIT_VALUE (tree->right))
5301     return NULL;
5302
5303   if (!IS_RIGHT_OP (tree->left))
5304     return NULL;
5305
5306   if (!IS_AST_LIT_VALUE (tree->left->right))
5307     return NULL;
5308
5309   return tree->left->left;
5310 }
5311
5312 /*-----------------------------------------------------------------*/
5313 /* isBitAndPowOf2 - helper function                                */
5314 /*-----------------------------------------------------------------*/
5315 static int
5316 isBitAndPow2 (ast * tree)
5317 {
5318   /* if this is not a bit and */
5319   if (!IS_BITAND (tree))
5320     return -1;
5321
5322   /* will look for tree of the form
5323      ( expr & (1 << litval) */
5324   if (!IS_AST_LIT_VALUE (tree->right))
5325     return -1;
5326
5327   return powof2 ((TYPE_TARGET_ULONG)AST_LIT_VALUE (tree->right));
5328 }
5329
5330 /*-----------------------------------------------------------------*/
5331 /* optimizeGetHbit - get highest order bit of the expression       */
5332 /*-----------------------------------------------------------------*/
5333 ast *
5334 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5335 {
5336   int i, j;
5337   ast * expr;
5338
5339   expr = isShiftRightLitVal_BitAndLitVal(tree);
5340   if (expr)
5341     {
5342       if ((AST_LIT_VALUE (tree->right) != 1) ||
5343           ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
5344           (j = (getSize (TTYPE (expr)) * 8 - 1))))
5345         expr = NULL;
5346     }
5347   if (!expr && (resultType == RESULT_TYPE_BIT))
5348     {
5349       expr = tree->left;
5350       if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5351         expr = NULL;
5352     }
5353   if (!expr)
5354     return tree;
5355
5356   /* make sure the port supports GETHBIT */
5357   if (port->hasExtBitOp
5358       && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5359     return tree;
5360
5361   return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5362 }
5363
5364 /*-----------------------------------------------------------------*/
5365 /* optimizeGetAbit - get a single bit of the expression            */
5366 /*-----------------------------------------------------------------*/
5367 ast *
5368 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5369 {
5370   ast * expr;
5371   ast * count = NULL;
5372
5373   expr = isShiftRightLitVal_BitAndLitVal(tree);
5374   if (expr)
5375     {
5376   if (AST_LIT_VALUE (tree->right) != 1)
5377         expr = NULL;
5378       count = tree->left->right;
5379     }
5380   if (!expr && (resultType == RESULT_TYPE_BIT))
5381     {
5382       int p2 = isBitAndPow2 (tree);
5383       if (p2 >= 0)
5384         {
5385           expr = tree->left;
5386           count = newAst_VALUE (valueFromLit (p2));
5387         }
5388     }
5389   if (!expr)
5390     return tree;
5391
5392   /* make sure the port supports GETABIT */
5393   if (port->hasExtBitOp
5394       && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5395     return tree;
5396
5397   return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5398
5399 }
5400
5401 /*-----------------------------------------------------------------*/
5402 /* optimizeGetByte - get a byte of the expression                  */
5403 /*-----------------------------------------------------------------*/
5404 ast *
5405 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5406 {
5407   unsigned int i = 0;
5408   ast * expr;
5409   ast * count = NULL;
5410
5411   expr = isShiftRightLitVal_BitAndLitVal(tree);
5412   if (expr)
5413     {
5414       i = (unsigned int) AST_LIT_VALUE (tree->left->right);
5415       count = tree->left->right;
5416       if (AST_LIT_VALUE (tree->right) != 0xFF)
5417         expr = NULL;
5418     }
5419   if (!expr && resultType == RESULT_TYPE_CHAR)
5420     {
5421       /* if this is a right shift over a multiple of 8 */
5422       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5423         {
5424           i = (unsigned int) AST_LIT_VALUE (tree->right);
5425           count = tree->right;
5426             expr = tree->left;
5427         }
5428     }
5429   if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5430     return tree;
5431
5432   /* make sure the port supports GETBYTE */
5433   if (port->hasExtBitOp
5434       && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5435     return tree;
5436
5437   return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5438 }
5439
5440 /*-----------------------------------------------------------------*/
5441 /* optimizeGetWord - get two bytes of the expression               */
5442 /*-----------------------------------------------------------------*/
5443 ast *
5444 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5445 {
5446   unsigned int i = 0;
5447   ast * expr;
5448   ast * count = NULL;
5449
5450   expr = isShiftRightLitVal_BitAndLitVal(tree);
5451   if (expr)
5452     {
5453       i = (unsigned int) AST_LIT_VALUE (tree->left->right);
5454       count = tree->left->right;
5455       if (AST_LIT_VALUE (tree->right) != 0xFFFF)
5456         expr = NULL;
5457     }
5458   if (!expr && resultType == RESULT_TYPE_INT)
5459     {
5460       /* if this is a right shift over a multiple of 8 */
5461       if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5462         {
5463           i = (unsigned int) AST_LIT_VALUE (tree->right);
5464           count = tree->right;
5465             expr = tree->left;
5466         }
5467     }
5468   if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5469     return tree;
5470
5471   /* make sure the port supports GETWORD */
5472   if (port->hasExtBitOp
5473       && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5474     return tree;
5475
5476   return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5477 }
5478
5479 /*-----------------------------------------------------------------*/
5480 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry     */
5481 /*-----------------------------------------------------------------*/
5482 ast *
5483 optimizeRRCRLC (ast * root)
5484 {
5485   /* will look for trees of the form
5486      (?expr << 1) | (?expr >> 7) or
5487      (?expr >> 7) | (?expr << 1) will make that
5488      into a RLC : operation ..
5489      Will also look for
5490      (?expr >> 1) | (?expr << 7) or
5491      (?expr << 7) | (?expr >> 1) will make that
5492      into a RRC operation
5493      note : by 7 I mean (number of bits required to hold the
5494      variable -1 ) */
5495   /* if the root operation is not a | operation then not */
5496   if (!IS_BITOR (root))
5497     return root;
5498
5499   /* I have to think of a better way to match patterns this sucks */
5500   /* that aside let's start looking for the first case : I use a
5501      negative check a lot to improve the efficiency */
5502   /* (?expr << 1) | (?expr >> 7) */
5503   if (IS_LEFT_OP (root->left) &&
5504       IS_RIGHT_OP (root->right))
5505     {
5506
5507       if (!SPEC_USIGN (TETYPE (root->left->left)))
5508         return root;
5509
5510       if (!IS_AST_LIT_VALUE (root->left->right) ||
5511           !IS_AST_LIT_VALUE (root->right->right))
5512         goto tryNext0;
5513
5514       /* make sure it is the same expression */
5515       if (!isAstEqual (root->left->left,
5516                        root->right->left))
5517         goto tryNext0;
5518
5519       if (AST_LIT_VALUE (root->left->right) != 1)
5520         goto tryNext0;
5521
5522       if (AST_LIT_VALUE (root->right->right) !=
5523           (getSize (TTYPE (root->left->left)) * 8 - 1))
5524         goto tryNext0;
5525
5526       /* make sure the port supports RLC */
5527       if (port->hasExtBitOp
5528           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5529         return root;
5530
5531       /* whew got the first case : create the AST */
5532       return newNode (RLC, root->left->left, NULL);
5533     }
5534
5535 tryNext0:
5536   /* check for second case */
5537   /* (?expr >> 7) | (?expr << 1) */
5538   if (IS_LEFT_OP (root->right) &&
5539       IS_RIGHT_OP (root->left))
5540     {
5541
5542       if (!SPEC_USIGN (TETYPE (root->left->left)))
5543         return root;
5544
5545       if (!IS_AST_LIT_VALUE (root->left->right) ||
5546           !IS_AST_LIT_VALUE (root->right->right))
5547         goto tryNext1;
5548
5549       /* make sure it is the same symbol */
5550       if (!isAstEqual (root->left->left,
5551                        root->right->left))
5552         goto tryNext1;
5553
5554       if (AST_LIT_VALUE (root->right->right) != 1)
5555         goto tryNext1;
5556
5557       if (AST_LIT_VALUE (root->left->right) !=
5558           (getSize (TTYPE (root->left->left)) * 8 - 1))
5559         goto tryNext1;
5560
5561       /* make sure the port supports RLC */
5562       if (port->hasExtBitOp
5563           && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5564         return root;
5565
5566       /* whew got the first case : create the AST */
5567       return newNode (RLC, root->left->left, NULL);
5568
5569     }
5570
5571 tryNext1:
5572   /* third case for RRC */
5573   /*  (?symbol >> 1) | (?symbol << 7) */
5574   if (IS_LEFT_OP (root->right) &&
5575       IS_RIGHT_OP (root->left))
5576     {
5577
5578       if (!SPEC_USIGN (TETYPE (root->left->left)))
5579         return root;
5580
5581       if (!IS_AST_LIT_VALUE (root->left->right) ||
5582           !IS_AST_LIT_VALUE (root->right->right))
5583         goto tryNext2;
5584
5585       /* make sure it is the same symbol */
5586       if (!isAstEqual (root->left->left,
5587                        root->right->left))
5588         goto tryNext2;
5589
5590       if (AST_LIT_VALUE (root->left->right) != 1)
5591         goto tryNext2;
5592
5593       if (AST_LIT_VALUE (root->right->right) !=
5594           (getSize (TTYPE (root->left->left)) * 8 - 1))
5595         goto tryNext2;
5596
5597       /* make sure the port supports RRC */
5598       if (port->hasExtBitOp
5599           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5600         return root;
5601
5602       /* whew got the first case : create the AST */
5603       return newNode (RRC, root->left->left, NULL);
5604
5605     }
5606 tryNext2:
5607   /* fourth and last case for now */
5608   /* (?symbol << 7) | (?symbol >> 1) */
5609   if (IS_RIGHT_OP (root->right) &&
5610       IS_LEFT_OP (root->left))
5611     {
5612
5613       if (!SPEC_USIGN (TETYPE (root->left->left)))
5614         return root;
5615
5616       if (!IS_AST_LIT_VALUE (root->left->right) ||
5617           !IS_AST_LIT_VALUE (root->right->right))
5618         return root;
5619
5620       /* make sure it is the same symbol */
5621       if (!isAstEqual (root->left->left,
5622                        root->right->left))
5623         return root;
5624
5625       if (AST_LIT_VALUE (root->right->right) != 1)
5626         return root;
5627
5628       if (AST_LIT_VALUE (root->left->right) !=
5629           (getSize (TTYPE (root->left->left)) * 8 - 1))
5630         return root;
5631
5632       /* make sure the port supports RRC */
5633       if (port->hasExtBitOp
5634           && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5635         return root;
5636
5637       /* whew got the first case : create the AST */
5638       return newNode (RRC, root->left->left, NULL);
5639
5640     }
5641
5642   /* not found return root */
5643   return root;
5644 }
5645
5646 /*-----------------------------------------------------------------*/
5647 /* optimizeSWAP :- optimize for nibble/byte/word swaps             */
5648 /*-----------------------------------------------------------------*/
5649 ast *
5650 optimizeSWAP (ast * root)
5651 {
5652   /* will look for trees of the form
5653      (?expr << 4) | (?expr >> 4) or
5654      (?expr >> 4) | (?expr << 4) will make that
5655      into a SWAP : operation ..
5656      note : by 4 I mean (number of bits required to hold the
5657      variable /2 ) */
5658   /* if the root operation is not a | operation then not */
5659   if (!IS_BITOR (root))
5660     return root;
5661
5662   /* (?expr << 4) | (?expr >> 4) */
5663   if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5664       || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5665     {
5666
5667       if (!SPEC_USIGN (TETYPE (root->left->left)))
5668         return root;
5669
5670       if (!IS_AST_LIT_VALUE (root->left->right) ||
5671           !IS_AST_LIT_VALUE (root->right->right))
5672         return root;
5673
5674       /* make sure it is the same expression */
5675       if (!isAstEqual (root->left->left,
5676                        root->right->left))
5677         return root;
5678
5679       if (AST_LIT_VALUE (root->left->right) !=
5680           (getSize (TTYPE (root->left->left)) * 4))
5681         return root;
5682
5683       if (AST_LIT_VALUE (root->right->right) !=
5684           (getSize (TTYPE (root->left->left)) * 4))
5685         return root;
5686
5687       /* make sure the port supports SWAP */
5688       if (port->hasExtBitOp
5689           && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5690         return root;
5691
5692       /* found it : create the AST */
5693       return newNode (SWAP, root->left->left, NULL);
5694     }
5695
5696
5697   /* not found return root */
5698   return root;
5699 }
5700
5701 /*-----------------------------------------------------------------*/
5702 /* optimizeCompare - optimizes compares for bit variables          */
5703 /*-----------------------------------------------------------------*/
5704 static ast *
5705 optimizeCompare (ast * root)
5706 {
5707   ast *optExpr = NULL;
5708   value *vleft;
5709   value *vright;
5710   unsigned int litValue;
5711
5712   /* if nothing then return nothing */
5713   if (!root)
5714     return NULL;
5715
5716   /* if not a compare op then do leaves */
5717   if (!IS_COMPARE_OP (root))
5718     {
5719       root->left = optimizeCompare (root->left);
5720       root->right = optimizeCompare (root->right);
5721       return root;
5722     }
5723
5724   /* if left & right are the same then depending
5725      of the operation do */
5726   if (isAstEqual (root->left, root->right))
5727     {
5728       switch (root->opval.op)
5729         {
5730         case '>':
5731         case '<':
5732         case NE_OP:
5733           optExpr = newAst_VALUE (constVal ("0"));
5734           break;
5735         case GE_OP:
5736         case LE_OP:
5737         case EQ_OP:
5738           optExpr = newAst_VALUE (constVal ("1"));
5739           break;
5740         }
5741
5742       return decorateType (optExpr, RESULT_TYPE_NONE);
5743     }
5744
5745   vleft = (root->left->type == EX_VALUE ?
5746            root->left->opval.val : NULL);
5747
5748   vright = (root->right->type == EX_VALUE ?
5749             root->right->opval.val : NULL);
5750
5751   /* if left is a BITVAR in BITSPACE */
5752   /* and right is a LITERAL then opt- */
5753   /* imize else do nothing       */
5754   if (vleft && vright &&
5755       IS_BITVAR (vleft->etype) &&
5756       IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5757       IS_LITERAL (vright->etype))
5758     {
5759
5760       /* if right side > 1 then comparison may never succeed */
5761       if ((litValue = (int) floatFromVal (vright)) > 1)
5762         {
5763           werror (W_BAD_COMPARE);
5764           goto noOptimize;
5765         }
5766
5767       if (litValue)
5768         {
5769           switch (root->opval.op)
5770             {
5771             case '>':           /* bit value greater than 1 cannot be */
5772               werror (W_BAD_COMPARE);
5773               goto noOptimize;
5774               break;
5775
5776             case '<':           /* bit value < 1 means 0 */
5777             case NE_OP:
5778               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5779               break;
5780
5781             case LE_OP: /* bit value <= 1 means no check */
5782               optExpr = newAst_VALUE (vright);
5783               break;
5784
5785             case GE_OP: /* bit value >= 1 means only check for = */
5786             case EQ_OP:
5787               optExpr = newAst_VALUE (vleft);
5788               break;
5789             }
5790         }
5791       else
5792         {                       /* literal is zero */
5793           switch (root->opval.op)
5794             {
5795             case '<':           /* bit value < 0 cannot be */
5796               werror (W_BAD_COMPARE);
5797               goto noOptimize;
5798               break;
5799
5800             case '>':           /* bit value > 0 means 1 */
5801             case NE_OP:
5802               optExpr = newAst_VALUE (vleft);
5803               break;
5804
5805             case LE_OP: /* bit value <= 0 means no check */
5806             case GE_OP: /* bit value >= 0 means no check */
5807               werror (W_BAD_COMPARE);
5808               goto noOptimize;
5809               break;
5810
5811             case EQ_OP: /* bit == 0 means ! of bit */
5812               optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5813               break;
5814             }
5815         }
5816       return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5817     }                           /* end-of-if of BITVAR */
5818
5819 noOptimize:
5820   return root;
5821 }
5822
5823 /*-----------------------------------------------------------------*/
5824 /* addSymToBlock : adds the symbol to the first block we find      */
5825 /*-----------------------------------------------------------------*/
5826 void
5827 addSymToBlock (symbol * sym, ast * tree)
5828 {
5829   /* reached end of tree or a leaf */
5830   if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5831     return;
5832
5833   /* found a block */
5834   if (IS_AST_OP (tree) &&
5835       tree->opval.op == BLOCK)
5836     {
5837
5838       symbol *lsym = copySymbol (sym);
5839
5840       lsym->next = AST_VALUES (tree, sym);
5841       AST_VALUES (tree, sym) = lsym;
5842       return;
5843     }
5844
5845   addSymToBlock (sym, tree->left);
5846   addSymToBlock (sym, tree->right);
5847 }
5848
5849 /*-----------------------------------------------------------------*/
5850 /* processRegParms - do processing for register parameters         */
5851 /*-----------------------------------------------------------------*/
5852 static void
5853 processRegParms (value * args, ast * body)
5854 {
5855   while (args)
5856     {
5857       if (IS_REGPARM (args->etype))
5858         addSymToBlock (args->sym, body);
5859       args = args->next;
5860     }
5861 }
5862
5863 /*-----------------------------------------------------------------*/
5864 /* resetParmKey - resets the operandkeys for the symbols           */
5865 /*-----------------------------------------------------------------*/
5866 DEFSETFUNC (resetParmKey)
5867 {
5868   symbol *sym = item;
5869
5870   sym->key = 0;
5871   sym->defs = NULL;
5872   sym->uses = NULL;
5873   sym->remat = 0;
5874   return 1;
5875 }
5876
5877
5878
5879 /*------------------------------------------------------------------*/
5880 /* fixupInlineLabel - change a label in an inlined function so that */
5881 /*                    it is always unique no matter how many times  */
5882 /*                    the function is inlined.                      */
5883 /*------------------------------------------------------------------*/
5884 static void
5885 fixupInlineLabel (symbol * sym)
5886 {
5887   char name[SDCC_NAME_MAX + 1];
5888   
5889   SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5890   strcpy (sym->name, name);
5891 }
5892
5893
5894 /*------------------------------------------------------------------*/
5895 /* copyAstLoc - copy location information (file, line, block, etc.) */
5896 /*              from one ast node to another                        */
5897 /*------------------------------------------------------------------*/
5898 static void
5899 copyAstLoc (ast * dest, ast * src)
5900 {
5901   dest->lineno = src->lineno;
5902   dest->filename = src->filename;
5903   dest->level = src->level;
5904   dest->block = src->block;
5905   dest->seqPoint = src->seqPoint;
5906   
5907 }
5908
5909
5910 /*-----------------------------------------------------------------*/
5911 /* fixupInline - perform various fixups on an inline function tree */
5912 /*               to take into account that it is no longer a       */
5913 /*               stand-alone function.                             */
5914 /*-----------------------------------------------------------------*/
5915 static void
5916 fixupInline (ast * tree, int level)
5917 {
5918   tree->block = currBlockno;
5919
5920   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
5921     {
5922       symbol * decls;
5923
5924       currBlockno++;
5925       level++;
5926
5927       /* Add any declared variables back into the symbol table */
5928       decls = tree->values.sym;
5929       while (decls)
5930         {
5931           decls->level = level;
5932           decls->block = currBlockno;
5933           addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
5934           decls = decls->next;
5935         }
5936     }
5937
5938   tree->level = level;
5939
5940   /* Update symbols */
5941   if (IS_AST_VALUE (tree) &&
5942       tree->opval.val->sym)
5943     {
5944       symbol * sym = tree->opval.val->sym;
5945
5946       sym->level = level;
5947       sym->block = currBlockno;
5948
5949       /* If the symbol is a label, we need to renumber it */
5950       if (sym->islbl)
5951         fixupInlineLabel (sym);
5952     }
5953
5954   /* Update IFX target labels */
5955   if (tree->type == EX_OP && tree->opval.op == IFX)
5956     {
5957       if (tree->trueLabel)
5958         fixupInlineLabel (tree->trueLabel);
5959       if (tree->falseLabel)
5960         fixupInlineLabel (tree->falseLabel);
5961     }
5962
5963   /* Replace RETURN with optional assignment and a GOTO to the end */
5964   /* of the inlined function */
5965   if (tree->type == EX_OP && tree->opval.op == RETURN)
5966     {
5967       ast * assignTree = NULL;
5968       ast * gotoTree;
5969
5970       if (inlineState.retsym && tree->right)
5971         {
5972           assignTree = newNode ('=',
5973                                 newAst_VALUE (symbolVal (inlineState.retsym)),
5974                                 tree->right);
5975           copyAstLoc (assignTree, tree);
5976         }
5977
5978       gotoTree = newNode (GOTO,
5979                           newAst_VALUE (symbolVal (inlineState.retlab)),
5980                           NULL);
5981       copyAstLoc (gotoTree, tree);
5982
5983       tree->opval.op = NULLOP;
5984       tree->left = assignTree;
5985       tree->right = gotoTree;
5986     }
5987
5988    /* Update any children */
5989    if (tree->left)
5990       fixupInline (tree->left, level);
5991    if (tree->right)
5992       fixupInline (tree->right, level);
5993
5994   if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
5995     {
5996       symbol * label = tree->left->opval.val->sym;
5997
5998       label->key = labelKey++;
5999       /* Add this label back into the symbol table */
6000       addSym (LabelTab, label, label->name, label->level, 0, 0);
6001     }
6002
6003
6004   if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6005     {
6006       level--;
6007     }
6008 }
6009
6010 /*-----------------------------------------------------------------*/
6011 /* inlineAddDecl - add a variable declaration to an ast block. It  */
6012 /*                 is also added to the symbol table if addSymTab  */
6013 /*                 is nonzero.                                     */
6014 /*-----------------------------------------------------------------*/
6015 static void
6016 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6017 {
6018   if (block != NULL)
6019     {
6020       symbol **decl = &(block->values.sym);
6021
6022       sym->level = block->level;
6023       sym->block = block->block;
6024
6025       while (*decl)
6026         {
6027           if (strcmp ((*decl)->name, sym->name) == 0)
6028             return;
6029           decl = &( (*decl)->next );
6030         }
6031
6032       *decl = sym;
6033
6034       if (addSymTab)
6035         addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6036
6037     }
6038 }
6039
6040
6041 /*-----------------------------------------------------------------*/
6042 /* inlineTempVar - create a temporary variable for inlining        */
6043 /*-----------------------------------------------------------------*/
6044 static symbol *
6045 inlineTempVar (sym_link * type, int level)
6046 {
6047   symbol * sym;
6048
6049   sym = newSymbol (genSymName(level), level );
6050   sym->type = copyLinkChain (type);
6051   sym->etype = getSpec(sym->type);
6052   SPEC_SCLS (sym->etype) = S_AUTO;
6053   SPEC_OCLS (sym->etype) = NULL;
6054   SPEC_EXTR (sym->etype) = 0;
6055   SPEC_STAT (sym->etype) = 0;
6056   if IS_SPEC (sym->type)
6057     SPEC_VOLATILE (sym->type) = 0;
6058   else
6059     DCL_PTR_VOLATILE (sym->type) = 0;
6060   SPEC_ABSA (sym->etype) = 0;
6061
6062   return sym;
6063 }
6064
6065
6066 /*-----------------------------------------------------------------*/
6067 /* inlineFindParmRecurse - recursive function for inlineFindParm   */
6068 /*-----------------------------------------------------------------*/
6069 static ast *
6070 inlineFindParmRecurse (ast * parms, int *index)
6071 {
6072   if (!parms)
6073     return NULL;
6074
6075   if (parms->type == EX_OP && parms->opval.op == PARAM)
6076   {
6077     ast * p;
6078
6079     p=inlineFindParmRecurse (parms->left, index);
6080     if (p)
6081       return p;
6082     p=inlineFindParmRecurse (parms->right, index);
6083     if (p)
6084       return p;
6085   }
6086   if (!*index)
6087     return parms;
6088   (*index)--;
6089   return NULL;
6090 }
6091
6092
6093 /*-----------------------------------------------------------------*/
6094 /* inlineFindParm - search an ast tree of parameters to find one   */
6095 /*                  at a particular index (0=first parameter).     */
6096 /*                  Returns NULL if not found.                     */
6097 /*-----------------------------------------------------------------*/
6098 static ast *
6099 inlineFindParm (ast * parms, int index)
6100 {
6101   return inlineFindParmRecurse (parms, &index);
6102 }
6103
6104
6105 /*-----------------------------------------------------------------*/
6106 /* expandInlineFuncs - replace calls to inline functions with the  */
6107 /*                     function itself                             */
6108 /*-----------------------------------------------------------------*/
6109 static void
6110 expandInlineFuncs (ast * tree, ast * block)
6111 {
6112   if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6113       && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6114     {
6115       symbol * func = tree->left->opval.val->sym;
6116       symbol * csym;
6117
6118       /* The symbol is probably not bound yet, so find the real one */
6119       csym = findSymWithLevel (SymbolTab, func);
6120       if (csym)
6121         func = csym;
6122
6123       /* Is this an inline function that we can inline? */
6124       if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6125         {
6126           symbol * retsym = NULL;
6127           symbol * retlab;
6128           ast * inlinetree;
6129           ast * inlinetree2;
6130           ast * temptree;
6131           value * args;
6132           int argIndex;
6133
6134           /* Generate a label for the inlined function to branch to */
6135           /* in case it contains a return statement */
6136           retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6137           retlab->isitmp = 1;
6138           retlab->islbl = 1;
6139           inlineState.retlab = retlab;
6140
6141           /* Build the subtree for the inlined function in the form: */
6142           /* { //inlinetree block                                    */
6143           /*   { //inlinetree2 block                                 */
6144           /*     inline_function_code;                               */
6145           /*     retlab:                                             */
6146           /*   }                                                     */
6147           /* }                                                       */
6148           temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6149           copyAstLoc (temptree, tree);
6150           temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6151           copyAstLoc (temptree, tree);
6152           temptree = newNode (BLOCK, NULL, temptree);
6153           copyAstLoc (temptree, tree);
6154           inlinetree2 = temptree;
6155           inlinetree = newNode (BLOCK, NULL, inlinetree2);
6156           copyAstLoc (inlinetree, tree);
6157
6158           /* To pass parameters to the inlined function, we need some  */
6159           /* intermediate variables. This avoids scoping problems      */
6160           /* when the parameter declaration names are used differently */
6161           /* during the function call. For example, a function         */
6162           /* declared as func(int x, int y) but called as func(y,x).   */
6163           /* { //inlinetree block                                      */
6164           /*   type1 temparg1;                                         */
6165           /*   ...                                                     */
6166           /*   typen tempargn;                                         */
6167           /*   temparg1 = argument1;                                   */
6168           /*   ...                                                     */
6169           /*   tempargn = argumentn;                                   */
6170           /*   { //inlinetree2 block                                   */
6171           /*     type1 param1;                                         */
6172           /*     ...                                                   */
6173           /*     typen paramn;                                         */
6174           /*     param1 = temparg1;                                    */
6175           /*     ...                                                   */
6176           /*     paramn = tempargn;                                    */
6177           /*     inline_function_code;                                 */
6178           /*     retlab:                                               */
6179           /*   }                                                       */
6180           /* }                                                         */
6181           args = FUNC_ARGS (func->type);
6182           argIndex = 0;
6183           while (args)
6184             {
6185               symbol * temparg;
6186               ast * passedarg;
6187               ast * assigntree;
6188               symbol * parm = copySymbol (args->sym);
6189
6190               temparg = inlineTempVar (args->sym->type, tree->level+1);
6191               inlineAddDecl (temparg, inlinetree, FALSE);
6192
6193               passedarg = inlineFindParm (tree->right, argIndex);
6194               assigntree = newNode ('=',
6195                                     newAst_VALUE (symbolVal (temparg)),
6196                                     passedarg);
6197               inlinetree->right = newNode (NULLOP,
6198                                            assigntree,
6199                                            inlinetree->right);
6200
6201               inlineAddDecl (parm, inlinetree2, FALSE);
6202               parm->_isparm = 0;
6203
6204               assigntree = newNode ('=',
6205                                     newAst_VALUE (symbolVal (parm)),
6206                                     newAst_VALUE (symbolVal (temparg)));
6207               inlinetree2->right = newNode (NULLOP,
6208                                            assigntree,
6209                                            inlinetree2->right);
6210
6211
6212               args = args->next;
6213               argIndex++;
6214             }
6215
6216           /* Handle the return type */
6217           if (!IS_VOID (func->type->next))
6218             {
6219               /* Create a temporary symbol to hold the return value and   */
6220               /* join it with the inlined function using the comma        */
6221               /* operator. The fixupInline function will take care of     */
6222               /* changing return statements into assignments to retsym.   */
6223               /* (parameter passing and return label omitted for clarity) */
6224               /* rettype retsym;                                          */
6225               /* ...                                                      */
6226               /* {{inline_function_code}}, retsym                         */
6227
6228               retsym = inlineTempVar (func->type->next, tree->level);
6229               inlineAddDecl (retsym, block, TRUE);
6230
6231               tree->opval.op = ',';
6232               tree->left = inlinetree;
6233               tree->right = newAst_VALUE (symbolVal (retsym));
6234             }
6235           else
6236             {
6237               tree->opval.op = NULLOP;
6238               tree->left = NULL;
6239               tree->right = inlinetree;
6240             }
6241           inlineState.retsym = retsym;
6242
6243           /* Renumber the various internal counters on the inlined   */
6244           /* function's tree nodes and symbols. Add the inlined      */
6245           /* function's local variables to the appropriate scope(s). */
6246           /* Convert inlined return statements to an assignment to   */
6247           /* retsym (if needed) and a goto retlab.                   */
6248           fixupInline (inlinetree, inlinetree->level);
6249           inlineState.count++;
6250         }
6251
6252     }
6253
6254   /* Recursively continue to search for functions to inline. */
6255   if (IS_AST_OP (tree))
6256     {
6257       if (tree->opval.op == BLOCK)
6258         block = tree;
6259
6260       if (tree->left)
6261         expandInlineFuncs (tree->left, block);
6262       if (tree->right)
6263         expandInlineFuncs (tree->right, block);
6264     }
6265 }
6266
6267
6268 /*-----------------------------------------------------------------*/
6269 /* createFunction - This is the key node that calls the iCode for  */
6270 /*                  generating the code for a function. Note code  */
6271 /*                  is generated function by function, later when  */
6272 /*                  add inter-procedural analysis this will change */
6273 /*-----------------------------------------------------------------*/
6274 ast *
6275 createFunction (symbol * name, ast * body)
6276 {
6277   ast *ex;
6278   symbol *csym;
6279   int stack = 0;
6280   sym_link *fetype;
6281   iCode *piCode = NULL;
6282
6283   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6284     fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6285
6286   /* if check function return 0 then some problem */
6287   if (checkFunction (name, NULL) == 0)
6288     return NULL;
6289
6290   /* create a dummy block if none exists */
6291   if (!body)
6292     body = newNode (BLOCK, NULL, NULL);
6293
6294   noLineno++;
6295
6296   /* check if the function name already in the symbol table */
6297   if ((csym = findSym (SymbolTab, NULL, name->name)))
6298     {
6299       name = csym;
6300       /* special case for compiler defined functions
6301          we need to add the name to the publics list : this
6302          actually means we are now compiling the compiler
6303          support routine */
6304       if (name->cdef)
6305         {
6306           addSet (&publics, name);
6307         }
6308     }
6309   else
6310     {
6311       addSymChain (&name);
6312       allocVariables (name);
6313     }
6314   name->lastLine = lexLineno;
6315   currFunc = name;
6316
6317   /* set the stack pointer */
6318   stackPtr  = -port->stack.direction * port->stack.call_overhead;
6319   xstackPtr = 0;
6320
6321   if (IFFUNC_ISISR (name->type))
6322     stackPtr -= port->stack.direction * port->stack.isr_overhead;
6323
6324   if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6325     {
6326       if (options.useXstack)
6327         xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6328       else
6329         stackPtr  -= port->stack.direction * port->stack.reent_overhead;
6330     }
6331
6332   fetype = getSpec (name->type);        /* get the specifier for the function */
6333   /* if this is a reentrant function then */
6334   if (IFFUNC_ISREENT (name->type))
6335     reentrant++;
6336
6337   inlineState.count = 0;
6338   expandInlineFuncs (body, NULL);
6339
6340   if (FUNC_ISINLINE (name->type))
6341     name->funcTree = copyAst (body);
6342
6343   allocParms (FUNC_ARGS(name->type));   /* allocate the parameters */
6344
6345   /* do processing for parameters that are passed in registers */
6346   processRegParms (FUNC_ARGS(name->type), body);
6347
6348   /* set the stack pointer */
6349   stackPtr = 0;
6350   xstackPtr = -1;
6351
6352   gatherImplicitVariables (body, NULL);  /* move implicit variables into blocks */
6353
6354   /* allocate & autoinit the block variables */
6355   processBlockVars (body, &stack, ALLOCATE);
6356
6357   /* name needs to be mangled */
6358   SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6359
6360   body = resolveSymbols (body); /* resolve the symbols */
6361   body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6362
6363   /* save the stack information */
6364   if (options.useXstack)
6365     name->xstack = SPEC_STAK (fetype) = stack;
6366   else
6367     name->stack = SPEC_STAK (fetype) = stack;
6368
6369   ex = newAst_VALUE (symbolVal (name)); /* create name */
6370   ex = newNode (FUNCTION, ex, body);
6371   ex->values.args = FUNC_ARGS(name->type);
6372   ex->decorated=1;
6373   if (options.dump_tree)
6374     PA(ex);
6375   if (fatalError)
6376     goto skipall;
6377
6378   /* Do not generate code for inline functions unless extern also */
6379   if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6380     goto skipall;
6381
6382   /* create the node & generate intermediate code */
6383   GcurMemmap = code;
6384   codeOutBuf = &code->oBuf;
6385   piCode = iCodeFromAst (ex);
6386   name->generated = 1;
6387
6388   if (fatalError)
6389     goto skipall;
6390
6391   eBBlockFromiCode (piCode);
6392
6393   /* if there are any statics then do them */
6394   if (staticAutos)
6395     {
6396       GcurMemmap = statsg;
6397       codeOutBuf = &statsg->oBuf;
6398       eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6399       staticAutos = NULL;
6400     }
6401
6402 skipall:
6403
6404   /* dealloc the block variables */
6405   processBlockVars (body, &stack, DEALLOCATE);
6406   outputDebugStackSymbols();
6407   /* deallocate paramaters */
6408   deallocParms (FUNC_ARGS(name->type));
6409
6410   if (IFFUNC_ISREENT (name->type))
6411     reentrant--;
6412
6413   /* we are done freeup memory & cleanup */
6414   noLineno--;
6415   if (port->reset_labelKey) labelKey = 1;
6416   name->key = 0;
6417   FUNC_HASBODY(name->type) = 1;
6418   addSet (&operKeyReset, name);
6419   applyToSet (operKeyReset, resetParmKey);
6420
6421   if (options.debug)
6422     cdbStructBlock(1);
6423
6424   cleanUpLevel (LabelTab, 0);
6425   cleanUpBlock (StructTab, 1);
6426   cleanUpBlock (TypedefTab, 1);
6427
6428   xstack->syms = NULL;
6429   istack->syms = NULL;
6430   return NULL;
6431 }
6432
6433
6434 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6435 /*-----------------------------------------------------------------*/
6436 /* ast_print : prints the ast (for debugging purposes)             */
6437 /*-----------------------------------------------------------------*/
6438
6439 void ast_print (ast * tree, FILE *outfile, int indent)
6440 {
6441
6442   if (!tree) return ;
6443
6444   /* can print only decorated trees */
6445   if (!tree->decorated) return;
6446
6447   /* if any child is an error | this one is an error do nothing */
6448   if (tree->isError ||
6449     (tree->left && tree->left->isError) ||
6450     (tree->right && tree->right->isError)) {
6451     fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6452   }
6453
6454
6455   /* print the line          */
6456   /* if not block & function */
6457   if (tree->type == EX_OP &&
6458     (tree->opval.op != FUNCTION &&
6459     tree->opval.op != BLOCK &&
6460     tree->opval.op != NULLOP)) {
6461   }
6462
6463   if (tree->opval.op == FUNCTION) {
6464     int arg=0;
6465     value *args=FUNC_ARGS(tree->left->opval.val->type);
6466     fprintf(outfile,"FUNCTION (%s=%p) type (",
6467       tree->left->opval.val->name, tree);
6468     printTypeChain (tree->left->opval.val->type->next,outfile);
6469     fprintf(outfile,") args (");
6470     do {
6471       if (arg) {
6472         fprintf (outfile, ", ");
6473       }
6474       printTypeChain (args ? args->type : NULL, outfile);
6475       arg++;
6476       args= args ? args->next : NULL;
6477     } while (args);
6478     fprintf(outfile,")\n");
6479     ast_print(tree->left,outfile,indent);
6480     ast_print(tree->right,outfile,indent);
6481     return ;
6482   }
6483   if (tree->opval.op == BLOCK) {
6484     symbol *decls = tree->values.sym;
6485     INDENT(indent,outfile);
6486     fprintf(outfile,"{\n");
6487     while (decls) {
6488       INDENT(indent+2,outfile);
6489       fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6490         decls->name, decls);
6491       printTypeChain(decls->type,outfile);
6492       fprintf(outfile,")\n");
6493
6494       decls = decls->next;
6495     }
6496     ast_print(tree->right,outfile,indent+2);
6497     INDENT(indent,outfile);
6498     fprintf(outfile,"}\n");
6499     return;
6500   }
6501   if (tree->opval.op == NULLOP) {
6502     ast_print(tree->left,outfile,indent);
6503     ast_print(tree->right,outfile,indent);
6504     return ;
6505   }
6506   INDENT(indent,outfile);
6507
6508   /*------------------------------------------------------------------*/
6509   /*----------------------------*/
6510   /*   leaf has been reached    */
6511   /*----------------------------*/
6512   /* if this is of type value */
6513   /* just get the type        */
6514   if (tree->type == EX_VALUE) {
6515
6516     if (IS_LITERAL (tree->opval.val->etype)) {
6517       fprintf(outfile,"CONSTANT (%p) value = ", tree);
6518       if (SPEC_USIGN (tree->opval.val->etype))
6519         fprintf(outfile,"%u", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val));
6520       else
6521         fprintf(outfile,"%d", (TYPE_TARGET_LONG) floatFromVal(tree->opval.val));
6522       fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) floatFromVal(tree->opval.val),
6523         floatFromVal(tree->opval.val));
6524     } else if (tree->opval.val->sym) {
6525       /* if the undefined flag is set then give error message */
6526       if (tree->opval.val->sym->undefined) {
6527         fprintf(outfile,"UNDEFINED SYMBOL ");
6528       } else {
6529         fprintf(outfile,"SYMBOL ");
6530       }
6531       fprintf(outfile,"(%s=%p @ %p)",
6532         tree->opval.val->sym->name, tree, tree->opval.val->sym);
6533     }
6534     if (tree->ftype) {
6535       fprintf(outfile," type (");
6536       printTypeChain(tree->ftype,outfile);
6537       fprintf(outfile,")\n");
6538     } else {
6539       fprintf(outfile,"\n");
6540     }
6541     return ;
6542   }
6543
6544   /* if type link for the case of cast */
6545   if (tree->type == EX_LINK) {
6546     fprintf(outfile,"TYPENODE (%p) type = (",tree);
6547     printTypeChain(tree->opval.lnk,outfile);
6548     fprintf(outfile,")\n");
6549     return ;
6550   }
6551
6552
6553   /* depending on type of operator do */
6554
6555   switch (tree->opval.op) {
6556     /*------------------------------------------------------------------*/
6557     /*----------------------------*/
6558     /*        array node          */
6559     /*----------------------------*/
6560   case '[':
6561     fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6562     printTypeChain(tree->ftype,outfile);
6563     fprintf(outfile,")\n");
6564     ast_print(tree->left,outfile,indent+2);
6565     ast_print(tree->right,outfile,indent+2);
6566     return;
6567
6568     /*------------------------------------------------------------------*/
6569     /*----------------------------*/
6570     /*      struct/union          */
6571     /*----------------------------*/
6572   case '.':
6573     fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6574     printTypeChain(tree->ftype,outfile);
6575     fprintf(outfile,")\n");
6576     ast_print(tree->left,outfile,indent+2);
6577     ast_print(tree->right,outfile,indent+2);
6578     return ;
6579
6580     /*------------------------------------------------------------------*/
6581     /*----------------------------*/
6582     /*    struct/union pointer    */
6583     /*----------------------------*/
6584   case PTR_OP:
6585     fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6586     printTypeChain(tree->ftype,outfile);
6587     fprintf(outfile,")\n");
6588     ast_print(tree->left,outfile,indent+2);
6589     ast_print(tree->right,outfile,indent+2);
6590     return ;
6591
6592     /*------------------------------------------------------------------*/
6593     /*----------------------------*/
6594     /*  ++/-- operation           */
6595     /*----------------------------*/
6596   case INC_OP:
6597     if (tree->left)
6598       fprintf(outfile,"post-");
6599     else
6600       fprintf(outfile,"pre-");
6601     fprintf(outfile,"INC_OP (%p) type (",tree);
6602     printTypeChain(tree->ftype,outfile);
6603     fprintf(outfile,")\n");
6604     ast_print(tree->left,outfile,indent+2); /* postincrement case */
6605     ast_print(tree->right,outfile,indent+2); /* preincrement case */
6606     return ;
6607
6608   case DEC_OP:
6609     if (tree->left)
6610       fprintf(outfile,"post-");
6611     else
6612       fprintf(outfile,"pre-");
6613     fprintf(outfile,"DEC_OP (%p) type (",tree);
6614     printTypeChain(tree->ftype,outfile);
6615     fprintf(outfile,")\n");
6616     ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6617     ast_print(tree->right,outfile,indent+2); /* predecrement case */
6618     return ;
6619
6620     /*------------------------------------------------------------------*/
6621     /*----------------------------*/
6622     /*  bitwise and               */
6623     /*----------------------------*/
6624   case '&':
6625     if (tree->right) {
6626       fprintf(outfile,"& (%p) type (",tree);
6627       printTypeChain(tree->ftype,outfile);
6628       fprintf(outfile,")\n");
6629       ast_print(tree->left,outfile,indent+2);
6630       ast_print(tree->right,outfile,indent+2);
6631     } else {
6632       fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6633       printTypeChain(tree->ftype,outfile);
6634       fprintf(outfile,")\n");
6635       ast_print(tree->left,outfile,indent+2);
6636       ast_print(tree->right,outfile,indent+2);
6637     }
6638     return ;
6639     /*----------------------------*/
6640     /*  bitwise or                */
6641     /*----------------------------*/
6642   case '|':
6643     fprintf(outfile,"OR (%p) type (",tree);
6644     printTypeChain(tree->ftype,outfile);
6645     fprintf(outfile,")\n");
6646     ast_print(tree->left,outfile,indent+2);
6647     ast_print(tree->right,outfile,indent+2);
6648     return ;
6649     /*------------------------------------------------------------------*/
6650     /*----------------------------*/
6651     /*  bitwise xor               */
6652     /*----------------------------*/
6653   case '^':
6654     fprintf(outfile,"XOR (%p) type (",tree);
6655     printTypeChain(tree->ftype,outfile);
6656     fprintf(outfile,")\n");
6657     ast_print(tree->left,outfile,indent+2);
6658     ast_print(tree->right,outfile,indent+2);
6659     return ;
6660
6661     /*------------------------------------------------------------------*/
6662     /*----------------------------*/
6663     /*  division                  */
6664     /*----------------------------*/
6665   case '/':
6666     fprintf(outfile,"DIV (%p) type (",tree);
6667     printTypeChain(tree->ftype,outfile);
6668     fprintf(outfile,")\n");
6669     ast_print(tree->left,outfile,indent+2);
6670     ast_print(tree->right,outfile,indent+2);
6671     return ;
6672     /*------------------------------------------------------------------*/
6673     /*----------------------------*/
6674     /*            modulus         */
6675     /*----------------------------*/
6676   case '%':
6677     fprintf(outfile,"MOD (%p) type (",tree);
6678     printTypeChain(tree->ftype,outfile);
6679     fprintf(outfile,")\n");
6680     ast_print(tree->left,outfile,indent+2);
6681     ast_print(tree->right,outfile,indent+2);
6682     return ;
6683
6684     /*------------------------------------------------------------------*/
6685     /*----------------------------*/
6686     /*  address dereference       */
6687     /*----------------------------*/
6688   case '*':                       /* can be unary  : if right is null then unary operation */
6689     if (!tree->right) {
6690       fprintf(outfile,"DEREF (%p) type (",tree);
6691       printTypeChain(tree->ftype,outfile);
6692       fprintf(outfile,")\n");
6693       ast_print(tree->left,outfile,indent+2);
6694       return ;
6695     }
6696     /*------------------------------------------------------------------*/
6697     /*----------------------------*/
6698     /*      multiplication        */
6699     /*----------------------------*/
6700     fprintf(outfile,"MULT (%p) type (",tree);
6701     printTypeChain(tree->ftype,outfile);
6702     fprintf(outfile,")\n");
6703     ast_print(tree->left,outfile,indent+2);
6704     ast_print(tree->right,outfile,indent+2);
6705     return ;
6706
6707
6708     /*------------------------------------------------------------------*/
6709     /*----------------------------*/
6710     /*    unary '+' operator      */
6711     /*----------------------------*/
6712   case '+':
6713     /* if unary plus */
6714     if (!tree->right) {
6715       fprintf(outfile,"UPLUS (%p) type (",tree);
6716       printTypeChain(tree->ftype,outfile);
6717       fprintf(outfile,")\n");
6718       ast_print(tree->left,outfile,indent+2);
6719     } else {
6720       /*------------------------------------------------------------------*/
6721       /*----------------------------*/
6722       /*      addition              */
6723       /*----------------------------*/
6724       fprintf(outfile,"ADD (%p) type (",tree);
6725       printTypeChain(tree->ftype,outfile);
6726       fprintf(outfile,")\n");
6727       ast_print(tree->left,outfile,indent+2);
6728       ast_print(tree->right,outfile,indent+2);
6729     }
6730     return;
6731     /*------------------------------------------------------------------*/
6732     /*----------------------------*/
6733     /*      unary '-'             */
6734     /*----------------------------*/
6735   case '-':                       /* can be unary   */
6736     if (!tree->right) {
6737       fprintf(outfile,"UMINUS (%p) type (",tree);
6738       printTypeChain(tree->ftype,outfile);
6739       fprintf(outfile,")\n");
6740       ast_print(tree->left,outfile,indent+2);
6741     } else {
6742       /*------------------------------------------------------------------*/
6743       /*----------------------------*/
6744       /*      subtraction           */
6745       /*----------------------------*/
6746       fprintf(outfile,"SUB (%p) type (",tree);
6747       printTypeChain(tree->ftype,outfile);
6748       fprintf(outfile,")\n");
6749       ast_print(tree->left,outfile,indent+2);
6750       ast_print(tree->right,outfile,indent+2);
6751     }
6752     return;
6753     /*------------------------------------------------------------------*/
6754     /*----------------------------*/
6755     /*    complement              */
6756     /*----------------------------*/
6757   case '~':
6758     fprintf(outfile,"COMPL (%p) type (",tree);
6759     printTypeChain(tree->ftype,outfile);
6760     fprintf(outfile,")\n");
6761     ast_print(tree->left,outfile,indent+2);
6762     return ;
6763     /*------------------------------------------------------------------*/
6764     /*----------------------------*/
6765     /*           not              */
6766     /*----------------------------*/
6767   case '!':
6768     fprintf(outfile,"NOT (%p) type (",tree);
6769     printTypeChain(tree->ftype,outfile);
6770     fprintf(outfile,")\n");
6771     ast_print(tree->left,outfile,indent+2);
6772     return ;
6773     /*------------------------------------------------------------------*/
6774     /*----------------------------*/
6775     /*           shift            */
6776     /*----------------------------*/
6777   case RRC:
6778     fprintf(outfile,"RRC (%p) type (",tree);
6779     printTypeChain(tree->ftype,outfile);
6780     fprintf(outfile,")\n");
6781     ast_print(tree->left,outfile,indent+2);
6782     return ;
6783
6784   case RLC:
6785     fprintf(outfile,"RLC (%p) type (",tree);
6786     printTypeChain(tree->ftype,outfile);
6787     fprintf(outfile,")\n");
6788     ast_print(tree->left,outfile,indent+2);
6789     return ;
6790   case SWAP:
6791     fprintf(outfile,"SWAP (%p) type (",tree);
6792     printTypeChain(tree->ftype,outfile);
6793     fprintf(outfile,")\n");
6794     ast_print(tree->left,outfile,indent+2);
6795     return ;
6796   case GETHBIT:
6797     fprintf(outfile,"GETHBIT (%p) type (",tree);
6798     printTypeChain(tree->ftype,outfile);
6799     fprintf(outfile,")\n");
6800     ast_print(tree->left,outfile,indent+2);
6801     return ;
6802   case GETABIT:
6803     fprintf(outfile,"GETABIT (%p) type (",tree);
6804     printTypeChain(tree->ftype,outfile);
6805     fprintf(outfile,")\n");
6806     ast_print(tree->left,outfile,indent+2);
6807     ast_print(tree->right,outfile,indent+2);
6808     return ;
6809   case GETBYTE:
6810     fprintf(outfile,"GETBYTE (%p) type (",tree);
6811     printTypeChain(tree->ftype,outfile);
6812     fprintf(outfile,")\n");
6813     ast_print(tree->left,outfile,indent+2);
6814     ast_print(tree->right,outfile,indent+2);
6815     return ;
6816   case GETWORD:
6817     fprintf(outfile,"GETWORD (%p) type (",tree);
6818     printTypeChain(tree->ftype,outfile);
6819     fprintf(outfile,")\n");
6820     ast_print(tree->left,outfile,indent+2);
6821     ast_print(tree->right,outfile,indent+2);
6822     return ;
6823   case LEFT_OP:
6824     fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6825     printTypeChain(tree->ftype,outfile);
6826     fprintf(outfile,")\n");
6827     ast_print(tree->left,outfile,indent+2);
6828     ast_print(tree->right,outfile,indent+2);
6829     return ;
6830   case RIGHT_OP:
6831     fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6832     printTypeChain(tree->ftype,outfile);
6833     fprintf(outfile,")\n");
6834     ast_print(tree->left,outfile,indent+2);
6835     ast_print(tree->right,outfile,indent+2);
6836     return ;
6837     /*------------------------------------------------------------------*/
6838     /*----------------------------*/
6839     /*         casting            */
6840     /*----------------------------*/
6841   case CAST:                      /* change the type   */
6842     fprintf(outfile,"CAST (%p) from type (",tree);
6843     printTypeChain(tree->right->ftype,outfile);
6844     fprintf(outfile,") to type (");
6845     printTypeChain(tree->ftype,outfile);
6846     fprintf(outfile,")\n");
6847     ast_print(tree->right,outfile,indent+2);
6848     return ;
6849
6850   case AND_OP:
6851     fprintf(outfile,"ANDAND (%p) type (",tree);
6852     printTypeChain(tree->ftype,outfile);
6853     fprintf(outfile,")\n");
6854     ast_print(tree->left,outfile,indent+2);
6855     ast_print(tree->right,outfile,indent+2);
6856     return ;
6857   case OR_OP:
6858     fprintf(outfile,"OROR (%p) type (",tree);
6859     printTypeChain(tree->ftype,outfile);
6860     fprintf(outfile,")\n");
6861     ast_print(tree->left,outfile,indent+2);
6862     ast_print(tree->right,outfile,indent+2);
6863     return ;
6864
6865     /*------------------------------------------------------------------*/
6866     /*----------------------------*/
6867     /*     comparison operators   */
6868     /*----------------------------*/
6869   case '>':
6870     fprintf(outfile,"GT(>) (%p) type (",tree);
6871     printTypeChain(tree->ftype,outfile);
6872     fprintf(outfile,")\n");
6873     ast_print(tree->left,outfile,indent+2);
6874     ast_print(tree->right,outfile,indent+2);
6875     return ;
6876   case '<':
6877     fprintf(outfile,"LT(<) (%p) type (",tree);
6878     printTypeChain(tree->ftype,outfile);
6879     fprintf(outfile,")\n");
6880     ast_print(tree->left,outfile,indent+2);
6881     ast_print(tree->right,outfile,indent+2);
6882     return ;
6883   case LE_OP:
6884     fprintf(outfile,"LE(<=) (%p) type (",tree);
6885     printTypeChain(tree->ftype,outfile);
6886     fprintf(outfile,")\n");
6887     ast_print(tree->left,outfile,indent+2);
6888     ast_print(tree->right,outfile,indent+2);
6889     return ;
6890   case GE_OP:
6891     fprintf(outfile,"GE(>=) (%p) type (",tree);
6892     printTypeChain(tree->ftype,outfile);
6893     fprintf(outfile,")\n");
6894     ast_print(tree->left,outfile,indent+2);
6895     ast_print(tree->right,outfile,indent+2);
6896     return ;
6897   case EQ_OP:
6898     fprintf(outfile,"EQ(==) (%p) type (",tree);
6899     printTypeChain(tree->ftype,outfile);
6900     fprintf(outfile,")\n");
6901     ast_print(tree->left,outfile,indent+2);
6902     ast_print(tree->right,outfile,indent+2);
6903     return ;
6904   case NE_OP:
6905     fprintf(outfile,"NE(!=) (%p) type (",tree);
6906     printTypeChain(tree->ftype,outfile);
6907     fprintf(outfile,")\n");
6908     ast_print(tree->left,outfile,indent+2);
6909     ast_print(tree->right,outfile,indent+2);
6910     /*------------------------------------------------------------------*/
6911     /*----------------------------*/
6912     /*             sizeof         */
6913     /*----------------------------*/
6914   case SIZEOF:            /* evaluate wihout code generation */
6915     fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
6916     return ;
6917
6918     /*------------------------------------------------------------------*/
6919     /*----------------------------*/
6920     /* conditional operator  '?'  */
6921     /*----------------------------*/
6922   case '?':
6923     fprintf(outfile,"QUEST(?) (%p) type (",tree);
6924     printTypeChain(tree->ftype,outfile);
6925     fprintf(outfile,")\n");
6926     ast_print(tree->left,outfile,indent+2);
6927     ast_print(tree->right,outfile,indent+2);
6928     return;
6929
6930   case ':':
6931     fprintf(outfile,"COLON(:) (%p) type (",tree);
6932     printTypeChain(tree->ftype,outfile);
6933     fprintf(outfile,")\n");
6934     ast_print(tree->left,outfile,indent+2);
6935     ast_print(tree->right,outfile,indent+2);
6936     return ;
6937
6938     /*------------------------------------------------------------------*/
6939     /*----------------------------*/
6940     /*    assignment operators    */
6941     /*----------------------------*/
6942   case MUL_ASSIGN:
6943     fprintf(outfile,"MULASS(*=) (%p) type (",tree);
6944     printTypeChain(tree->ftype,outfile);
6945     fprintf(outfile,")\n");
6946     ast_print(tree->left,outfile,indent+2);
6947     ast_print(tree->right,outfile,indent+2);
6948     return;
6949   case DIV_ASSIGN:
6950     fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
6951     printTypeChain(tree->ftype,outfile);
6952     fprintf(outfile,")\n");
6953     ast_print(tree->left,outfile,indent+2);
6954     ast_print(tree->right,outfile,indent+2);
6955     return;
6956   case AND_ASSIGN:
6957     fprintf(outfile,"ANDASS(&=) (%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 OR_ASSIGN:
6964     fprintf(outfile,"ORASS(|=) (%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 XOR_ASSIGN:
6971     fprintf(outfile,"XORASS(^=) (%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 RIGHT_ASSIGN:
6978     fprintf(outfile,"RSHFTASS(>>=) (%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 LEFT_ASSIGN:
6985     fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
6986     printTypeChain(tree->ftype,outfile);
6987     fprintf(outfile,")\n");
6988     ast_print(tree->left,outfile,indent+2);
6989     ast_print(tree->right,outfile,indent+2);
6990     return;
6991     /*------------------------------------------------------------------*/
6992     /*----------------------------*/
6993     /*    -= operator             */
6994     /*----------------------------*/
6995   case SUB_ASSIGN:
6996     fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
6997     printTypeChain(tree->ftype,outfile);
6998     fprintf(outfile,")\n");
6999     ast_print(tree->left,outfile,indent+2);
7000     ast_print(tree->right,outfile,indent+2);
7001     return;
7002     /*------------------------------------------------------------------*/
7003     /*----------------------------*/
7004     /*          += operator       */
7005     /*----------------------------*/
7006   case ADD_ASSIGN:
7007     fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7008     printTypeChain(tree->ftype,outfile);
7009     fprintf(outfile,")\n");
7010     ast_print(tree->left,outfile,indent+2);
7011     ast_print(tree->right,outfile,indent+2);
7012     return;
7013     /*------------------------------------------------------------------*/
7014     /*----------------------------*/
7015     /*      straight assignemnt   */
7016     /*----------------------------*/
7017   case '=':
7018     fprintf(outfile,"ASSIGN(=) (%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     /*      comma operator        */
7027     /*----------------------------*/
7028   case ',':
7029     fprintf(outfile,"COMMA(,) (%p) type (",tree);
7030     printTypeChain(tree->ftype,outfile);
7031     fprintf(outfile,")\n");
7032     ast_print(tree->left,outfile,indent+2);
7033     ast_print(tree->right,outfile,indent+2);
7034     return;
7035     /*------------------------------------------------------------------*/
7036     /*----------------------------*/
7037     /*       function call        */
7038     /*----------------------------*/
7039   case CALL:
7040   case PCALL:
7041     fprintf(outfile,"CALL (%p) type (",tree);
7042     printTypeChain(tree->ftype,outfile);
7043     fprintf(outfile,")\n");
7044     ast_print(tree->left,outfile,indent+2);
7045     ast_print(tree->right,outfile,indent+2);
7046     return;
7047   case PARAM:
7048     fprintf(outfile,"PARMS\n");
7049     ast_print(tree->left,outfile,indent+2);
7050     if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7051       ast_print(tree->right,outfile,indent+2);
7052     }
7053     return ;
7054     /*------------------------------------------------------------------*/
7055     /*----------------------------*/
7056     /*     return statement       */
7057     /*----------------------------*/
7058   case RETURN:
7059     fprintf(outfile,"RETURN (%p) type (",tree);
7060     if (tree->right) {
7061       printTypeChain(tree->right->ftype,outfile);
7062     }
7063     fprintf(outfile,")\n");
7064     ast_print(tree->right,outfile,indent+2);
7065     return ;
7066     /*------------------------------------------------------------------*/
7067     /*----------------------------*/
7068     /*     label statement        */
7069     /*----------------------------*/
7070   case LABEL :
7071     fprintf(outfile,"LABEL (%p)\n",tree);
7072     ast_print(tree->left,outfile,indent+2);
7073     ast_print(tree->right,outfile,indent);
7074     return;
7075     /*------------------------------------------------------------------*/
7076     /*----------------------------*/
7077     /*     switch statement       */
7078     /*----------------------------*/
7079   case SWITCH:
7080     {
7081       value *val;
7082       fprintf(outfile,"SWITCH (%p) ",tree);
7083       ast_print(tree->left,outfile,0);
7084       for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7085         INDENT(indent+2,outfile);
7086         fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7087           (int) floatFromVal(val),
7088           tree->values.switchVals.swNum,
7089           (int) floatFromVal(val));
7090       }
7091       ast_print(tree->right,outfile,indent);
7092     }
7093     return ;
7094     /*------------------------------------------------------------------*/
7095     /*----------------------------*/
7096     /* ifx Statement              */
7097     /*----------------------------*/
7098   case IFX:
7099     fprintf(outfile,"IF (%p) \n",tree);
7100     ast_print(tree->left,outfile,indent+2);
7101     if (tree->trueLabel) {
7102       INDENT(indent+2,outfile);
7103       fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7104     }
7105     if (tree->falseLabel) {
7106       INDENT(indent+2,outfile);
7107       fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7108     }
7109     ast_print(tree->right,outfile,indent+2);
7110     return ;
7111     /*----------------------------*/
7112     /* goto Statement              */
7113     /*----------------------------*/
7114   case GOTO:
7115     fprintf(outfile,"GOTO (%p) \n",tree);
7116     ast_print(tree->left,outfile,indent+2);
7117     fprintf(outfile,"\n");
7118     return ;
7119     /*------------------------------------------------------------------*/
7120     /*----------------------------*/
7121     /* for Statement              */
7122     /*----------------------------*/
7123   case FOR:
7124     fprintf(outfile,"FOR (%p) \n",tree);
7125     if (AST_FOR( tree, initExpr)) {
7126       INDENT(indent+2,outfile);
7127       fprintf(outfile,"INIT EXPR ");
7128       ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7129     }
7130     if (AST_FOR( tree, condExpr)) {
7131       INDENT(indent+2,outfile);
7132       fprintf(outfile,"COND EXPR ");
7133       ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7134     }
7135     if (AST_FOR( tree, loopExpr)) {
7136       INDENT(indent+2,outfile);
7137       fprintf(outfile,"LOOP EXPR ");
7138       ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7139     }
7140     fprintf(outfile,"FOR LOOP BODY \n");
7141     ast_print(tree->left,outfile,indent+2);
7142     return ;
7143   case CRITICAL:
7144     fprintf(outfile,"CRITICAL (%p) \n",tree);
7145     ast_print(tree->left,outfile,indent+2);
7146   default:
7147     return ;
7148   }
7149 }
7150
7151 void PA(ast *t)
7152 {
7153   ast_print(t,stdout,0);
7154 }
7155
7156 /*-----------------------------------------------------------------*/
7157 /* astErrors : returns non-zero if errors present in tree          */
7158 /*-----------------------------------------------------------------*/
7159 int astErrors(ast *t)
7160 {
7161   int errors=0;
7162
7163   if (t)
7164     {
7165       if (t->isError)
7166         errors++;
7167
7168       if (t->type == EX_VALUE
7169           && t->opval.val->sym
7170           && t->opval.val->sym->undefined)
7171         errors++;
7172
7173       errors += astErrors(t->left);
7174       errors += astErrors(t->right);
7175     }
7176
7177   return errors;
7178 }