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