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