1 /*-------------------------------------------------------------------------
2 SDCCast.c - source file for parser support & all ast related routines
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
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
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.
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.
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 -------------------------------------------------------------------------*/
25 #define DEBUG_CF(x) /* puts(x); */
31 set *operKeyReset = NULL;
32 ast *staticAutos = NULL;
35 int count; /* number of inline functions inserted */
36 symbol * retsym; /* variable for inlined function return value */
37 symbol * retlab; /* label ending inlined function (virtual return) */
40 #define LRVAL(x) x->left->rvalue
41 #define RRVAL(x) x->right->rvalue
42 #define TRVAL(x) x->rvalue
43 #define LLVAL(x) x->left->lvalue
44 #define RLVAL(x) x->right->lvalue
45 #define TLVAL(x) x->lvalue
46 #define RTYPE(x) x->right->ftype
47 #define RETYPE(x) x->right->etype
48 #define LTYPE(x) x->left->ftype
49 #define LETYPE(x) x->left->etype
50 #define TTYPE(x) x->ftype
51 #define TETYPE(x) x->etype
57 symbol *currFunc=NULL;
58 static ast *createIval (ast *, sym_link *, initList *, ast *, ast *);
59 static ast *createIvalCharPtr (ast *, sym_link *, ast *, ast *);
60 static ast *optimizeCompare (ast *);
61 ast *optimizeRRCRLC (ast *);
62 ast *optimizeSWAP (ast *);
63 ast *optimizeGetHbit (ast *, RESULT_TYPE);
64 ast *optimizeGetAbit (ast *, RESULT_TYPE);
65 ast *optimizeGetByte (ast *, RESULT_TYPE);
66 ast *optimizeGetWord (ast *, RESULT_TYPE);
67 static ast *backPatchLabels (ast *, symbol *, symbol *);
70 memmap *GcurMemmap=NULL; /* points to the memmap that's currently active */
71 struct dbuf_s *codeOutBuf;
75 printTypeChain (tree->ftype, stdout);
80 /*-----------------------------------------------------------------*/
81 /* newAst - creates a fresh node for an expression tree */
82 /*-----------------------------------------------------------------*/
84 newAst_ (unsigned type)
88 ex = Safe_alloc ( sizeof (ast));
91 ex->lineno = (noLineno ? 0 : lexLineno);
92 ex->filename = lexFilename;
93 ex->level = NestLevel;
94 ex->block = currBlockno;
95 ex->initMode = inInitMode;
96 ex->seqPoint = seqPointNo;
101 newAst_VALUE (value * val)
103 ast *ex = newAst_ (EX_VALUE);
109 newAst_OP (unsigned op)
111 ast *ex = newAst_ (EX_OP);
117 newAst_LINK (sym_link * val)
119 ast *ex = newAst_ (EX_LINK);
124 /*-----------------------------------------------------------------*/
125 /* newNode - creates a new node */
126 /*-----------------------------------------------------------------*/
128 newNode (long op, ast * left, ast * right)
139 /*-----------------------------------------------------------------*/
140 /* newIfxNode - creates a new Ifx Node */
141 /*-----------------------------------------------------------------*/
143 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
147 /* if this is a literal then we already know the result */
148 if (condAst->etype && IS_LITERAL (condAst->etype))
150 /* then depending on the expression value */
151 if (floatFromVal (condAst->opval.val))
152 ifxNode = newNode (GOTO,
153 newAst_VALUE (symbolVal (trueLabel)),
156 ifxNode = newNode (GOTO,
157 newAst_VALUE (symbolVal (falseLabel)),
162 ifxNode = newNode (IFX, condAst, NULL);
163 ifxNode->trueLabel = trueLabel;
164 ifxNode->falseLabel = falseLabel;
170 /*-----------------------------------------------------------------*/
171 /* copyAstValues - copies value portion of ast if needed */
172 /*-----------------------------------------------------------------*/
174 copyAstValues (ast * dest, ast * src)
176 switch (src->opval.op)
179 dest->values.sym = copySymbolChain (src->values.sym);
183 dest->values.switchVals.swVals =
184 copyValue (src->values.switchVals.swVals);
185 dest->values.switchVals.swDefault =
186 src->values.switchVals.swDefault;
187 dest->values.switchVals.swNum =
188 src->values.switchVals.swNum;
192 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
196 dest->values.constlist = copyLiteralList(src->values.constlist);
200 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
201 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
202 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
203 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
204 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
205 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
206 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
211 /*-----------------------------------------------------------------*/
212 /* copyAst - makes a copy of a given astession */
213 /*-----------------------------------------------------------------*/
222 dest = Safe_alloc ( sizeof (ast));
224 dest->type = src->type;
225 dest->filename = src->filename;
226 dest->lineno = src->lineno;
227 dest->level = src->level;
228 dest->funcName = src->funcName;
229 dest->reversed = src->reversed;
232 dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
234 /* if this is a leaf */
236 if (src->type == EX_VALUE)
238 dest->opval.val = copyValue (src->opval.val);
243 if (src->type == EX_LINK)
245 dest->opval.lnk = copyLinkChain (src->opval.lnk);
249 dest->opval.op = src->opval.op;
251 /* if this is a node that has special values */
252 copyAstValues (dest, src);
254 dest->trueLabel = copySymbol (src->trueLabel);
255 dest->falseLabel = copySymbol (src->falseLabel);
256 dest->left = copyAst (src->left);
257 dest->right = copyAst (src->right);
263 /*-----------------------------------------------------------------*/
264 /* removeIncDecOps: remove for side effects in *_ASSIGN's */
265 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
266 /*-----------------------------------------------------------------*/
267 ast *removeIncDecOps (ast * tree) {
269 // traverse the tree and remove inc/dec ops
274 if (tree->type == EX_OP &&
275 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
282 tree->left=removeIncDecOps(tree->left);
283 tree->right=removeIncDecOps(tree->right);
288 /*-----------------------------------------------------------------*/
289 /* removePreIncDecOps: remove for side effects in *_ASSIGN's */
290 /* "*++s += 3" -> "*++s = *++s + 3" */
291 /*-----------------------------------------------------------------*/
292 ast *removePreIncDecOps (ast * tree) {
294 // traverse the tree and remove pre-inc/dec ops
299 if (tree->type == EX_OP &&
300 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
305 tree->left=removePreIncDecOps(tree->left);
306 tree->right=removePreIncDecOps(tree->right);
311 /*-----------------------------------------------------------------*/
312 /* removePostIncDecOps: remove for side effects in *_ASSIGN's */
313 /* "*s++ += 3" -> "*s++ = *s++ + 3" */
314 /*-----------------------------------------------------------------*/
315 ast *removePostIncDecOps (ast * tree) {
317 // traverse the tree and remove pre-inc/dec ops
322 if (tree->type == EX_OP &&
323 (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
328 tree->left=removePostIncDecOps(tree->left);
329 tree->right=removePostIncDecOps(tree->right);
334 /*-----------------------------------------------------------------*/
335 /* replaceAstWithTemporary: Replace the AST pointed to by the arg */
336 /* with a reference to a new temporary variable. Returns*/
337 /* an AST which assigns the original value to the */
339 /*-----------------------------------------------------------------*/
340 static ast *replaceAstWithTemporary(ast **treeptr)
342 symbol *sym = newSymbol (genSymName(NestLevel), NestLevel );
345 /* Tell gatherImplicitVariables() to automatically give the
346 symbol the correct type */
351 tempvar = newNode('=', newAst_VALUE(symbolVal(sym)), *treeptr);
352 *treeptr = newAst_VALUE(symbolVal(sym));
359 /*-----------------------------------------------------------------*/
360 /* createRMW: Create a read-modify-write expression, using a */
361 /* temporary variable if necessary to avoid duplicating */
362 /* any side effects, for use in e.g. */
363 /* foo()->count += 5; becomes */
364 /* tmp = foo(); tmp->count = tmp->count + 5; */
365 /*-----------------------------------------------------------------*/
366 ast * createRMW (ast *target, unsigned op, ast *operand)
368 ast *readval, *writeval;
369 ast *tempvar1 = NULL;
370 ast *tempvar2 = NULL;
373 if (!target || !operand) {
377 /* we need to create two copies of target: one to read from and
378 one to write to. but we need to do this without duplicating
379 any side effects that may be contained in the tree. */
381 if (IS_AST_OP(target)) {
382 /* if this is a dereference, put the referenced item in the temporary */
383 if (IS_DEREF_OP(target) || target->opval.op == PTR_OP) {
384 /* create a new temporary containing the item being dereferenced */
385 if (hasSEFcalls(target->left))
386 tempvar1 = replaceAstWithTemporary(&(target->left));
387 } else if (target->opval.op == '[') {
388 /* Array access is similar, but we have to avoid side effects in
389 both values [WIML: Why not transform a[b] to *(a+b) in parser?] */
390 if (hasSEFcalls(target->left))
391 tempvar1 = replaceAstWithTemporary(&(target->left));
392 if (hasSEFcalls(target->right))
393 tempvar2 = replaceAstWithTemporary(&(target->right));
394 } else if ((target->opval.op == INC_OP) || (target->opval.op == DEC_OP)) {
395 /* illegal pre/post-increment/decrement */
396 werrorfl (target->filename, target->lineno, E_LVALUE_REQUIRED, "=");
398 /* we would have to handle '.', but it is not generated any more */
399 wassertl(target->opval.op != '.', "obsolete opcode in tree");
401 /* no other kinds of ASTs are lvalues and can contain side effects */
406 writeval = copyAst(target);
408 result = newNode('=', writeval, newNode(op, readval, operand));
410 result = newNode(',', tempvar2, result);
412 result = newNode(',', tempvar1, result);
418 /*-----------------------------------------------------------------*/
419 /* hasSEFcalls - returns TRUE if tree has a function call, */
420 /* inc/decrement, or other side effect */
421 /*-----------------------------------------------------------------*/
423 hasSEFcalls (ast * tree)
428 if (tree->type == EX_OP &&
429 (tree->opval.op == CALL ||
430 tree->opval.op == PCALL ||
431 tree->opval.op == '=' ||
432 tree->opval.op == INC_OP ||
433 tree->opval.op == DEC_OP))
436 return (hasSEFcalls (tree->left) |
437 hasSEFcalls (tree->right));
440 /*-----------------------------------------------------------------*/
441 /* isAstEqual - compares two asts & returns 1 if they are equal */
442 /*-----------------------------------------------------------------*/
444 isAstEqual (ast * t1, ast * t2)
453 if (t1->type != t2->type)
459 if (t1->opval.op != t2->opval.op)
461 return (isAstEqual (t1->left, t2->left) &&
462 isAstEqual (t1->right, t2->right));
466 if (t1->opval.val->sym)
468 if (!t2->opval.val->sym)
471 return isSymbolEqual (t1->opval.val->sym,
476 if (t2->opval.val->sym)
479 return (floatFromVal (t1->opval.val) ==
480 floatFromVal (t2->opval.val));
484 /* only compare these two types */
492 /*-----------------------------------------------------------------*/
493 /* resolveSymbols - resolve symbols from the symbol table */
494 /*-----------------------------------------------------------------*/
496 resolveSymbols (ast * tree)
498 /* walk the entire tree and check for values */
499 /* with symbols if we find one then replace */
500 /* symbol with that from the symbol table */
507 /* if not block & function */
508 if (tree->type == EX_OP &&
509 (tree->opval.op != FUNCTION &&
510 tree->opval.op != BLOCK &&
511 tree->opval.op != NULLOP))
513 filename = tree->filename;
514 lineno = tree->lineno;
518 /* make sure we resolve the true & false labels for ifx */
519 if (tree->type == EX_OP && tree->opval.op == IFX)
525 if ((csym = findSym (LabelTab, tree->trueLabel,
526 tree->trueLabel->name)))
527 tree->trueLabel = csym;
529 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
530 tree->trueLabel->name);
533 if (tree->falseLabel)
535 if ((csym = findSym (LabelTab,
537 tree->falseLabel->name)))
538 tree->falseLabel = csym;
540 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
541 tree->falseLabel->name);
545 /* if this is a label resolve it from the labelTab */
546 if (IS_AST_VALUE (tree) &&
547 tree->opval.val->sym &&
548 tree->opval.val->sym->islbl)
550 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
551 tree->opval.val->sym->name);
554 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
555 tree->opval.val->sym->name);
557 tree->opval.val->sym = csym;
559 goto resolveChildren;
562 /* do only for leafs */
563 if (IS_AST_VALUE (tree) &&
564 tree->opval.val->sym &&
565 !tree->opval.val->sym->implicit)
567 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
569 /* if found in the symbol table & they are not the same */
570 if (csym && tree->opval.val->sym != csym)
572 tree->opval.val->sym = csym;
573 tree->opval.val->type = csym->type;
574 tree->opval.val->etype = csym->etype;
577 /* if not found in the symbol table */
578 /* mark it as undefined & assume it */
579 /* is an integer in data space */
580 if (!csym && !tree->opval.val->sym->implicit)
582 /* if this is a function name then */
583 /* mark it as returning an int */
586 tree->opval.val->sym->type = newLink (DECLARATOR);
587 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
588 tree->opval.val->sym->type->next =
589 tree->opval.val->sym->etype = newIntLink ();
590 tree->opval.val->etype = tree->opval.val->etype;
591 tree->opval.val->type = tree->opval.val->sym->type;
592 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
593 tree->opval.val->sym->name);
594 //tree->opval.val->sym->undefined = 1;
595 allocVariables (tree->opval.val->sym);
599 tree->opval.val->sym->undefined = 1;
600 tree->opval.val->type =
601 tree->opval.val->etype = newIntLink ();
602 tree->opval.val->sym->type =
603 tree->opval.val->sym->etype = newIntLink ();
609 resolveSymbols (tree->left);
610 resolveSymbols (tree->right);
615 /*------------------------------------------------------------------------*/
616 /* setAstFileLine - walks a ast tree & sets the file name and line number */
617 /*------------------------------------------------------------------------*/
618 int setAstFileLine (ast * tree, char *filename, int lineno)
623 tree->filename = filename;
624 tree->lineno = lineno;
625 setAstFileLine (tree->left, filename, lineno);
626 setAstFileLine (tree->right, filename, lineno);
630 /*-----------------------------------------------------------------*/
631 /* funcOfType :- function of type with name */
632 /*-----------------------------------------------------------------*/
634 funcOfType (char *name, sym_link * type, sym_link * argType,
638 /* create the symbol */
639 sym = newSymbol (name, 0);
641 /* setup return value */
642 sym->type = newLink (DECLARATOR);
643 DCL_TYPE (sym->type) = FUNCTION;
644 sym->type->next = copyLinkChain (type);
645 sym->etype = getSpec (sym->type);
646 FUNC_ISREENT(sym->type) = rent ? 1 : 0;
648 /* if arguments required */
652 args = FUNC_ARGS(sym->type) = newValue ();
656 args->type = copyLinkChain (argType);
657 args->etype = getSpec (args->type);
658 SPEC_EXTR(args->etype)=1;
661 args = args->next = newValue ();
668 allocVariables (sym);
673 /*-----------------------------------------------------------------*/
674 /* funcOfTypeVarg :- function of type with name and argtype */
675 /*-----------------------------------------------------------------*/
677 funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
682 /* create the symbol */
683 sym = newSymbol (name, 0);
685 /* setup return value */
686 sym->type = newLink (DECLARATOR);
687 DCL_TYPE (sym->type) = FUNCTION;
688 sym->type->next = typeFromStr(rtype);
689 sym->etype = getSpec (sym->type);
691 /* if arguments required */
694 args = FUNC_ARGS(sym->type) = newValue ();
696 for ( i = 0 ; i < nArgs ; i++ ) {
697 args->type = typeFromStr(atypes[i]);
698 args->etype = getSpec (args->type);
699 SPEC_EXTR(args->etype)=1;
700 if ((i + 1) == nArgs) break;
701 args = args->next = newValue ();
708 allocVariables (sym);
713 /*-----------------------------------------------------------------*/
714 /* reverseParms - will reverse a parameter tree */
715 /*-----------------------------------------------------------------*/
717 reverseParms (ast * ptree)
723 /* top down if we find a nonParm tree then quit */
724 if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
726 /* The various functions expect the parameter tree to be right heavy. */
727 /* Rotate the tree to be left heavy so that after reversal it is */
728 /* right heavy again. */
729 while ((ttree = ptree->right) && ttree->type == EX_OP &&
730 ttree->opval.op == PARAM)
732 ptree->right = ttree->right;
733 ttree->right = ttree->left;
734 ttree->left = ptree->left;
740 ptree->left = ptree->right;
741 ptree->right = ttree;
743 reverseParms (ptree->left);
744 reverseParms (ptree->right);
750 /*-----------------------------------------------------------------*/
751 /* processParms - makes sure the parameters are okay and do some */
752 /* processing with them */
753 /*-----------------------------------------------------------------*/
755 processParms (ast *func,
758 int *parmNumber, /* unused, although updated */
761 RESULT_TYPE resultType;
764 /* if none of them exist */
765 if (!defParm && !*actParm)
770 if (getenv("DEBUG_SANITY"))
772 fprintf (stderr, "processParms: %s ", defParm->name);
774 /* make sure the type is complete and sane */
775 checkTypeSanity(defParm->etype, defParm->name);
778 if (IS_CODEPTR (func->ftype))
779 functype = func->ftype->next;
781 functype = func->ftype;
783 /* if the function is being called via a pointer & */
784 /* it has not been defined reentrant then we cannot */
785 /* have parameters */
786 /* PIC16 port can... */
787 if (!TARGET_IS_PIC16)
789 if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
791 werror (E_NONRENT_ARGS);
797 /* if defined parameters ended but actual parameters */
798 /* exist and this is not defined as a variable arg */
799 if (!defParm && *actParm && !IFFUNC_HASVARARGS(functype))
801 werror (E_TOO_MANY_PARMS);
805 /* if defined parameters present but no actual parameters */
806 if (defParm && !*actParm)
808 werror (E_TOO_FEW_PARMS);
812 /* if this is a PARAM node then match left & right */
813 if ((*actParm)->type == EX_OP && (*actParm)->opval.op == PARAM)
815 (*actParm)->decorated = 1;
816 return (processParms (func, defParm,
817 &(*actParm)->left, parmNumber, FALSE) ||
818 processParms (func, defParm ? defParm->next : NULL,
819 &(*actParm)->right, parmNumber, rightmost));
821 else if (defParm) /* not vararg */
823 /* If we have found a value node by following only right-hand links,
824 * then we know that there are no more values after us.
826 * Therefore, if there are more defined parameters, the caller didn't
829 if (rightmost && defParm->next)
831 werror (E_TOO_FEW_PARMS);
836 /* decorate parameter */
837 resultType = defParm ? getResultTypeFromType (defParm->type) :
839 *actParm = decorateType (*actParm, resultType);
841 if (IS_VOID((*actParm)->ftype))
843 werror (E_VOID_VALUE_USED);
847 /* If this is a varargs function... */
848 if (!defParm && *actParm && IFFUNC_HASVARARGS(functype))
853 /* don't perform integer promotion of explicitly typecasted variable arguments
854 * if sdcc extensions are enabled */
855 if (options.std_sdcc &&
856 (IS_CAST_OP (*actParm) ||
857 (IS_AST_SYM_VALUE (*actParm) && AST_VALUES (*actParm, removedCast)) ||
858 (IS_AST_LIT_VALUE (*actParm) && AST_VALUES (*actParm, literalFromCast))))
860 /* Parameter was explicitly typecast; don't touch it. */
864 ftype = (*actParm)->ftype;
866 /* If it's a char, upcast to int. */
867 if (IS_INTEGRAL (ftype)
868 && (getSize (ftype) < (unsigned) INTSIZE))
870 newType = newAst_LINK(INTTYPE);
873 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
875 newType = newAst_LINK (copyLinkChain(ftype));
876 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
879 if (IS_AGGREGATE (ftype))
881 newType = newAst_LINK (copyLinkChain (ftype));
882 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
887 /* cast required; change this op to a cast. */
888 (*actParm)->decorated = 0;
889 *actParm = newNode (CAST, newType, *actParm);
890 (*actParm)->filename = (*actParm)->right->filename;
891 (*actParm)->lineno = (*actParm)->right->lineno;
893 decorateType (*actParm, RESULT_TYPE_NONE);
898 /* if defined parameters ended but actual has not & */
900 if (!defParm && *actParm &&
901 (options.stackAuto || IFFUNC_ISREENT (functype)))
904 resolveSymbols (*actParm);
906 /* the parameter type must be at least castable */
907 if (compareType (defParm->type, (*actParm)->ftype) == 0)
909 werror (E_INCOMPAT_TYPES);
910 printFromToType ((*actParm)->ftype, defParm->type);
914 /* if the parameter is castable then add the cast */
915 if (compareType (defParm->type, (*actParm)->ftype) < 0)
919 resultType = getResultTypeFromType (defParm->etype);
920 pTree = resolveSymbols (copyAst (*actParm));
922 /* now change the current one to a cast */
923 (*actParm)->type = EX_OP;
924 (*actParm)->opval.op = CAST;
925 (*actParm)->left = newAst_LINK (defParm->type);
926 (*actParm)->right = pTree;
927 (*actParm)->decorated = 0; /* force typechecking */
928 decorateType (*actParm, IS_GENPTR (defParm->type) ? RESULT_TYPE_GPTR : resultType);
931 /* make a copy and change the regparm type to the defined parm */
932 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
933 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
934 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
936 /* if the function is being called via a pointer & */
937 /* this parameter is not passed in registers */
938 /* then the function must be defined reentrant */
939 if (IS_FUNCPTR (func->ftype) && !SPEC_REGPARM ((*actParm)->etype) &&
940 !IFFUNC_ISREENT (functype) && !options.stackAuto)
942 werror (E_NONRENT_ARGS);
951 /*-----------------------------------------------------------------*/
952 /* createIvalType - generates ival for basic types */
953 /*-----------------------------------------------------------------*/
955 createIvalType (ast * sym, sym_link * type, initList * ilist)
959 /* if initList is deep */
960 if (ilist && ilist->type == INIT_DEEP)
961 ilist = ilist->init.deep;
964 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
966 iExpr = newAst_VALUE (valueFromLit (0));
967 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
970 /*-----------------------------------------------------------------*/
971 /* createIvalStruct - generates initial value for structures */
972 /*-----------------------------------------------------------------*/
974 createIvalStruct (ast *sym, sym_link *type, initList *ilist, ast *rootValue)
980 sym_link * etype = getSpec (type);
982 if (ilist && ilist->type != INIT_DEEP)
984 werror (E_INIT_STRUCT, "");
988 iloop = ilist ? ilist->init.deep : NULL;
990 for (sflds = SPEC_STRUCT (type)->fields; sflds; sflds = sflds->next)
992 /* if we have come to end */
993 if (!iloop && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
996 if (!IS_BITFIELD (sflds->type) || !SPEC_BUNNAMED (sflds->etype))
999 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
1000 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
1001 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast, rootValue)), RESULT_TYPE_NONE);
1002 iloop = iloop ? iloop->next : NULL;
1008 if (IS_AST_VALUE (sym))
1009 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1010 W_EXCESS_INITIALIZERS, "struct",
1011 sym->opval.val->sym->name);
1013 werrorfl (sym->filename, sym->lineno, E_INIT_COUNT);
1019 /*-----------------------------------------------------------------*/
1020 /* createIvalArray - generates code for array initialization */
1021 /*-----------------------------------------------------------------*/
1023 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1027 int lcnt = 0, size = 0;
1028 literalList *literalL;
1029 sym_link * etype = getSpec (type);
1031 /* take care of the special case */
1032 /* array of characters can be init */
1034 if (IS_CHAR (type->next))
1035 if ((rast = createIvalCharPtr (sym,
1037 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1040 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1042 /* not the special case */
1043 if (ilist && ilist->type != INIT_DEEP)
1045 werror (E_INIT_STRUCT, "");
1049 iloop = ilist ? ilist->init.deep : NULL;
1050 lcnt = DCL_ELEM (type);
1053 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1058 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL, lcnt))
1062 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1064 rast = newNode(ARRAYINIT, aSym, NULL);
1065 rast->values.constlist = literalL;
1067 // Make sure size is set to length of initializer list.
1071 iloop = iloop->next;
1074 if (lcnt && size > lcnt)
1076 // Array size was specified, and we have more initializers than needed.
1077 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1078 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1088 (!lcnt || !DCL_ELEM (type) || !AST_SYMBOL (rootValue)->islocal || SPEC_STAT (etype)))
1093 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1094 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1095 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1097 iloop = (iloop ? iloop->next : NULL);
1099 /* no of elements given and we */
1100 /* have generated for all of them */
1103 // is this a better way? at least it won't crash
1104 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1105 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1112 /* if we have not been given a size */
1113 if (!DCL_ELEM (type))
1115 /* check, if it's a flexible array */
1116 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1117 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1119 DCL_ELEM (type) = size;
1122 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1126 /*-----------------------------------------------------------------*/
1127 /* createIvalCharPtr - generates initial values for char pointers */
1128 /*-----------------------------------------------------------------*/
1130 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1135 /* if this is a pointer & right is a literal array then */
1136 /* just assignment will do */
1137 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1138 SPEC_SCLS (iexpr->etype) == S_CODE)
1139 && IS_ARRAY (iexpr->ftype)))
1140 return newNode ('=', sym, iexpr);
1142 /* left side is an array so we have to assign each element */
1145 /* for each character generate an assignment */
1146 /* to the array element */
1148 unsigned int symsize = getSize (type);
1150 if (!AST_SYMBOL (rootVal)->islocal || SPEC_STAT (getSpec (type)))
1153 for (i = 0; i < symsize; ++i)
1155 rast = newNode (NULLOP,
1159 newAst_VALUE (valueFromLit ((float) i))),
1160 newAst_VALUE (valueFromLit (0))));
1163 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1166 if ((IS_LITERAL (iexpr->etype) ||
1167 SPEC_SCLS (iexpr->etype) == S_CODE)
1168 && IS_ARRAY (iexpr->ftype))
1170 /* for each character generate an assignment */
1171 /* to the array element */
1172 char *s = SPEC_CVAL (iexpr->etype).v_char;
1174 unsigned int symsize = getSize (type);
1176 size = getSize (iexpr->ftype);
1177 if (symsize && size > symsize)
1181 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1183 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1189 for (i = 0; i < size; i++)
1191 rast = newNode (NULLOP,
1195 newAst_VALUE (valueFromLit ((float) i))),
1196 newAst_VALUE (valueFromLit (*s++))));
1199 // now WE don't need iexpr's symbol anymore
1200 freeStringSymbol(AST_SYMBOL(iexpr));
1202 /* if we have not been given a size */
1203 if (!DCL_ELEM (type))
1205 /* check, if it's a flexible array */
1206 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1207 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1209 DCL_ELEM (type) = size;
1212 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1218 /*-----------------------------------------------------------------*/
1219 /* createIvalPtr - generates initial value for pointers */
1220 /*-----------------------------------------------------------------*/
1222 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1228 if (ilist && ilist->type == INIT_DEEP)
1229 ilist = ilist->init.deep;
1231 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1233 /* if character pointer */
1234 if (IS_CHAR (type->next))
1235 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1238 return newNode ('=', sym, iexpr);
1241 /*-----------------------------------------------------------------*/
1242 /* createIval - generates code for initial value */
1243 /*-----------------------------------------------------------------*/
1245 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1249 if (!ilist && (!AST_SYMBOL (rootValue)->islocal || SPEC_STAT (getSpec (type))))
1252 /* if structure then */
1253 if (IS_STRUCT (type))
1254 rast = createIvalStruct (sym, type, ilist, rootValue);
1256 /* if this is a pointer */
1258 rast = createIvalPtr (sym, type, ilist, rootValue);
1260 /* if this is an array */
1261 if (IS_ARRAY (type))
1262 rast = createIvalArray (sym, type, ilist, rootValue);
1264 /* if type is SPECIFIER */
1266 rast = createIvalType (sym, type, ilist);
1269 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1271 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1274 /*-----------------------------------------------------------------*/
1275 /* initAggregates - initialises aggregate variables with initv */
1276 /*-----------------------------------------------------------------*/
1277 ast * initAggregates (symbol * sym, initList * ival, ast * wid)
1279 ast *newAst = newAst_VALUE (symbolVal (sym));
1280 return createIval (newAst, sym->type, ival, wid, newAst);
1283 /*-----------------------------------------------------------------*/
1284 /* gatherAutoInit - creates assignment expressions for initial */
1286 /*-----------------------------------------------------------------*/
1288 gatherAutoInit (symbol * autoChain)
1295 for (sym = autoChain; sym; sym = sym->next)
1297 /* resolve the symbols in the ival */
1299 resolveIvalSym (sym->ival, sym->type);
1302 /* if we are PIC16 port,
1303 * and this is a static,
1304 * and have initial value,
1305 * and not S_CODE, don't emit in gs segment,
1306 * but allow glue.c:pic16emitRegularMap to put symbol
1307 * in idata section */
1308 if(TARGET_IS_PIC16 &&
1309 IS_STATIC (sym->etype) && sym->ival
1310 && SPEC_SCLS(sym->etype) != S_CODE) {
1311 SPEC_SCLS (sym->etype) = S_DATA;
1316 /* if this is a static variable & has an */
1317 /* initial value the code needs to be lifted */
1318 /* here to the main portion since they can be */
1319 /* initialised only once at the start */
1320 if (IS_STATIC (sym->etype) && sym->ival &&
1321 SPEC_SCLS (sym->etype) != S_CODE)
1325 /* insert the symbol into the symbol table */
1326 /* with level = 0 & name = rname */
1327 newSym = copySymbol (sym);
1328 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1330 /* now lift the code to main */
1331 if (IS_AGGREGATE (sym->type)) {
1332 work = initAggregates (sym, sym->ival, NULL);
1334 if (getNelements(sym->type, sym->ival)>1) {
1335 werrorfl (sym->fileDef, sym->lineDef,
1336 W_EXCESS_INITIALIZERS, "scalar",
1339 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1340 list2expr (sym->ival));
1343 setAstFileLine (work, sym->fileDef, sym->lineDef);
1347 staticAutos = newNode (NULLOP, staticAutos, work);
1354 /* if there is an initial value */
1355 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1357 initList *ilist = sym->ival;
1359 while (ilist->type == INIT_DEEP)
1361 ilist = ilist->init.deep;
1364 /* update lineno for error msg */
1365 filename = sym->fileDef;
1366 lineno = sym->lineDef;
1367 setAstFileLine (ilist->init.node, sym->fileDef, sym->lineDef);
1369 if (IS_AGGREGATE (sym->type))
1371 work = initAggregates (sym, sym->ival, NULL);
1375 if (getNelements(sym->type, sym->ival)>1)
1377 werrorfl (sym->fileDef, sym->lineDef,
1378 W_EXCESS_INITIALIZERS, "scalar",
1381 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1382 list2expr (sym->ival));
1386 setAstFileLine (work, sym->fileDef, sym->lineDef);
1390 init = newNode (NULLOP, init, work);
1399 /*-----------------------------------------------------------------*/
1400 /* freeStringSymbol - delete a literal string if no more usage */
1401 /*-----------------------------------------------------------------*/
1402 void freeStringSymbol(symbol *sym) {
1403 /* make sure this is a literal string */
1404 assert (sym->isstrlit);
1405 if (--sym->isstrlit == 0) { // lower the usage count
1406 memmap *segment=SPEC_OCLS(sym->etype);
1408 deleteSetItem(&segment->syms, sym);
1413 /*-----------------------------------------------------------------*/
1414 /* stringToSymbol - creates a symbol from a literal string */
1415 /*-----------------------------------------------------------------*/
1417 stringToSymbol (value * val)
1419 char name[SDCC_NAME_MAX + 1];
1420 static int charLbl = 0;
1425 // have we heard this before?
1426 for (sp = statsg->syms; sp; sp = sp->next)
1429 size = getSize (sym->type);
1430 if (sym->isstrlit && size == getSize (val->type) &&
1431 !memcmp (SPEC_CVAL (sym->etype).v_char, SPEC_CVAL (val->etype).v_char, size))
1433 // yes, this is old news. Don't publish it again.
1434 sym->isstrlit++; // but raise the usage count
1435 return symbolVal (sym);
1439 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1440 sym = newSymbol (name, 0); /* make it @ level 0 */
1441 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1443 /* copy the type from the value passed */
1444 sym->type = copyLinkChain (val->type);
1445 sym->etype = getSpec (sym->type);
1446 /* change to storage class & output class */
1447 SPEC_SCLS (sym->etype) = S_CODE;
1448 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1449 SPEC_STAT (sym->etype) = 1;
1450 /* make the level & block = 0 */
1451 sym->block = sym->level = 0;
1453 /* create an ival */
1454 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1459 allocVariables (sym);
1462 return symbolVal (sym);
1466 /*-----------------------------------------------------------------*/
1467 /* processBlockVars - will go thru the ast looking for block if */
1468 /* a block is found then will allocate the syms */
1469 /* will also gather the auto inits present */
1470 /*-----------------------------------------------------------------*/
1472 processBlockVars (ast * tree, int *stack, int action)
1477 /* if this is a block */
1478 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1482 if (action == ALLOCATE)
1484 *stack += allocVariables (tree->values.sym);
1485 autoInit = gatherAutoInit (tree->values.sym);
1487 /* if there are auto inits then do them */
1489 tree->left = newNode (NULLOP, autoInit, tree->left);
1491 else /* action is deallocate */
1492 deallocLocal (tree->values.sym);
1495 processBlockVars (tree->left, stack, action);
1496 processBlockVars (tree->right, stack, action);
1500 /*-------------------------------------------------------------*/
1501 /* constExprTree - returns TRUE if this tree is a constant */
1503 /*-------------------------------------------------------------*/
1504 bool constExprTree (ast *cexpr) {
1510 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1512 switch (cexpr->type)
1515 if (IS_AST_LIT_VALUE(cexpr)) {
1516 // this is a literal
1519 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1520 // a function's address will never change
1523 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1524 // an array's address will never change
1527 if (IS_AST_SYM_VALUE(cexpr) &&
1528 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1529 // a symbol in code space will never change
1530 // This is only for the 'char *s="hallo"' case and will have to leave
1531 //printf(" code space symbol");
1536 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1537 "unexpected link in expression tree\n");
1540 if (cexpr->opval.op==ARRAYINIT) {
1541 // this is a list of literals
1544 if (cexpr->opval.op=='=') {
1545 return constExprTree(cexpr->right);
1547 if (cexpr->opval.op==CAST) {
1548 // cast ignored, maybe we should throw a warning here?
1549 return constExprTree(cexpr->right);
1551 if (cexpr->opval.op=='&') {
1554 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1557 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1562 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1567 /*-----------------------------------------------------------------*/
1568 /* constExprValue - returns the value of a constant expression */
1569 /* or NULL if it is not a constant expression */
1570 /*-----------------------------------------------------------------*/
1572 constExprValue (ast * cexpr, int check)
1574 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1576 /* if this is not a constant then */
1577 if (!IS_LITERAL (cexpr->ftype))
1579 /* then check if this is a literal array
1581 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1582 SPEC_CVAL (cexpr->etype).v_char &&
1583 IS_ARRAY (cexpr->ftype))
1585 value *val = valFromType (cexpr->ftype);
1586 SPEC_SCLS (val->etype) = S_LITERAL;
1587 val->sym = cexpr->opval.val->sym;
1588 val->sym->type = copyLinkChain (cexpr->ftype);
1589 val->sym->etype = getSpec (val->sym->type);
1590 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1594 /* if we are casting a literal value then */
1595 if (IS_AST_OP (cexpr) &&
1596 cexpr->opval.op == CAST &&
1597 IS_LITERAL (cexpr->right->ftype))
1599 return valCastLiteral (cexpr->ftype,
1600 floatFromVal (cexpr->right->opval.val));
1603 if (IS_AST_VALUE (cexpr))
1605 return cexpr->opval.val;
1609 werror (E_CONST_EXPECTED, "found expression");
1614 /* return the value */
1615 if (IS_AST_VALUE (cexpr))
1617 return cexpr->opval.val;
1622 /*-----------------------------------------------------------------*/
1623 /* isLabelInAst - will return true if a given label is found */
1624 /*-----------------------------------------------------------------*/
1626 isLabelInAst (symbol * label, ast * tree)
1628 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1631 if (IS_AST_OP (tree) &&
1632 tree->opval.op == LABEL &&
1633 isSymbolEqual (AST_SYMBOL (tree->left), label))
1636 return isLabelInAst (label, tree->right) &&
1637 isLabelInAst (label, tree->left);
1640 /*-----------------------------------------------------------------*/
1641 /* isLoopCountable - return true if the loop count can be determi- */
1642 /* -ned at compile time . */
1643 /*-----------------------------------------------------------------*/
1645 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1646 symbol ** sym, ast ** init, ast ** end)
1649 /* the loop is considered countable if the following
1650 conditions are true :-
1652 a) initExpr :- <sym> = <const>
1653 b) condExpr :- <sym> < <const1>
1654 c) loopExpr :- <sym> ++
1657 /* first check the initExpr */
1658 if (IS_AST_OP (initExpr) &&
1659 initExpr->opval.op == '=' && /* is assignment */
1660 IS_AST_SYM_VALUE (initExpr->left))
1661 { /* left is a symbol */
1663 *sym = AST_SYMBOL (initExpr->left);
1664 *init = initExpr->right;
1669 /* don't reverse loop with volatile counter */
1670 if (IS_VOLATILE ((*sym)->type))
1673 /* for now the symbol has to be of
1675 if (!IS_INTEGRAL ((*sym)->type))
1678 /* now check condExpr */
1679 if (IS_AST_OP (condExpr))
1682 switch (condExpr->opval.op)
1685 if (IS_AST_SYM_VALUE (condExpr->left) &&
1686 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1687 IS_AST_LIT_VALUE (condExpr->right))
1689 *end = condExpr->right;
1695 if (IS_AST_OP (condExpr->left) &&
1696 condExpr->left->opval.op == '>' &&
1697 IS_AST_LIT_VALUE (condExpr->left->right) &&
1698 IS_AST_SYM_VALUE (condExpr->left->left) &&
1699 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1702 *end = newNode ('+', condExpr->left->right,
1703 newAst_VALUE (constCharVal (1)));
1716 /* check loop expression is of the form <sym>++ */
1717 if (!IS_AST_OP (loopExpr))
1720 /* check if <sym> ++ */
1721 if (loopExpr->opval.op == INC_OP)
1727 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1728 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1735 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1736 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1744 if (loopExpr->opval.op == ADD_ASSIGN)
1747 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1748 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1749 IS_AST_LIT_VALUE (loopExpr->right) &&
1750 AST_ULONG_VALUE (loopExpr->right) != 1)
1758 /*-----------------------------------------------------------------*/
1759 /* astHasVolatile - returns true if ast contains any volatile */
1760 /*-----------------------------------------------------------------*/
1762 astHasVolatile (ast * tree)
1767 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1770 if (IS_AST_OP (tree))
1771 return astHasVolatile (tree->left) ||
1772 astHasVolatile (tree->right);
1777 /*-----------------------------------------------------------------*/
1778 /* astHasPointer - return true if the ast contains any ptr variable */
1779 /*-----------------------------------------------------------------*/
1781 astHasPointer (ast * tree)
1786 if (IS_AST_LINK (tree))
1789 /* if we hit an array expression then check
1790 only the left side */
1791 if (IS_AST_OP (tree) && tree->opval.op == '[')
1792 return astHasPointer (tree->left);
1794 if (IS_AST_VALUE (tree))
1795 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1797 return astHasPointer (tree->left) ||
1798 astHasPointer (tree->right);
1802 /*-----------------------------------------------------------------*/
1803 /* astHasSymbol - return true if the ast has the given symbol */
1804 /*-----------------------------------------------------------------*/
1806 astHasSymbol (ast * tree, symbol * sym)
1808 if (!tree || IS_AST_LINK (tree))
1811 if (IS_AST_VALUE (tree))
1813 if (IS_AST_SYM_VALUE (tree))
1814 return isSymbolEqual (AST_SYMBOL (tree), sym);
1819 return astHasSymbol (tree->left, sym) ||
1820 astHasSymbol (tree->right, sym);
1823 /*-----------------------------------------------------------------*/
1824 /* astHasDeref - return true if the ast has an indirect access */
1825 /*-----------------------------------------------------------------*/
1827 astHasDeref (ast * tree)
1829 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1832 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1834 return astHasDeref (tree->left) || astHasDeref (tree->right);
1837 /*-----------------------------------------------------------------*/
1838 /* isConformingBody - the loop body has to conform to a set of */
1839 /* rules for the loop to be considered reversible read on for rules*/
1840 /*-----------------------------------------------------------------*/
1842 isConformingBody (ast * pbody, symbol * sym, ast * body)
1845 /* we are going to do a pre-order traversal of the
1846 tree && check for the following conditions. (essentially
1847 a set of very shallow tests )
1848 a) the sym passed does not participate in any arithmetic operation
1849 b) There are no function calls
1850 c) all jumps are within the body
1851 d) address of loop control variable not taken
1852 e) if an assignment has a pointer on the left hand side make sure
1853 right does not have loop control variable
1856 /* if we reach the end or a leaf then true */
1857 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1860 /* if anything else is "volatile" */
1861 if (IS_VOLATILE (TETYPE (pbody)))
1864 /* we will walk the body in a pre-order traversal for
1866 switch (pbody->opval.op)
1868 /*------------------------------------------------------------------*/
1870 // if the loopvar is used as an index
1871 /* array op is commutative -- must check both left & right */
1872 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1875 return isConformingBody (pbody->right, sym, body)
1876 && isConformingBody (pbody->left, sym, body);
1878 /*------------------------------------------------------------------*/
1883 /*------------------------------------------------------------------*/
1887 /* sure we are not sym is not modified */
1889 IS_AST_SYM_VALUE (pbody->left) &&
1890 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1894 IS_AST_SYM_VALUE (pbody->right) &&
1895 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1900 /*------------------------------------------------------------------*/
1902 case '*': /* can be unary : if right is null then unary operation */
1907 /* if right is NULL then unary operation */
1908 /*------------------------------------------------------------------*/
1909 /*----------------------------*/
1911 /*----------------------------*/
1914 if (IS_AST_SYM_VALUE (pbody->left) &&
1915 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1918 return isConformingBody (pbody->left, sym, body);
1922 if (astHasSymbol (pbody->left, sym) ||
1923 astHasSymbol (pbody->right, sym))
1928 /*------------------------------------------------------------------*/
1939 if (IS_AST_SYM_VALUE (pbody->left) &&
1940 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1943 if (IS_AST_SYM_VALUE (pbody->right) &&
1944 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1947 return isConformingBody (pbody->left, sym, body) &&
1948 isConformingBody (pbody->right, sym, body);
1956 if (IS_AST_SYM_VALUE (pbody->left) &&
1957 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1959 return isConformingBody (pbody->left, sym, body);
1961 /*------------------------------------------------------------------*/
1973 case SIZEOF: /* evaluate wihout code generation */
1975 if (IS_AST_SYM_VALUE (pbody->left) &&
1976 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1979 if (IS_AST_SYM_VALUE (pbody->right) &&
1980 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1983 return isConformingBody (pbody->left, sym, body) &&
1984 isConformingBody (pbody->right, sym, body);
1986 /*------------------------------------------------------------------*/
1989 /* if left has a pointer & right has loop
1990 control variable then we cannot */
1991 if (astHasPointer (pbody->left) &&
1992 astHasSymbol (pbody->right, sym))
1994 if (astHasVolatile (pbody->left))
1997 if (IS_AST_SYM_VALUE (pbody->left)) {
1998 // if the loopvar has an assignment
1999 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
2001 // if the loopvar is used in another (maybe conditional) block
2002 if (astHasSymbol (pbody->right, sym) &&
2003 (pbody->level >= body->level)) {
2008 if (astHasVolatile (pbody->left))
2011 if (astHasDeref(pbody->right))
2014 return isConformingBody (pbody->left, sym, body) &&
2015 isConformingBody (pbody->right, sym, body);
2026 assert ("Parser should not have generated this\n");
2028 /*------------------------------------------------------------------*/
2029 /*----------------------------*/
2030 /* comma operator */
2031 /*----------------------------*/
2033 return isConformingBody (pbody->left, sym, body) &&
2034 isConformingBody (pbody->right, sym, body);
2036 /*------------------------------------------------------------------*/
2037 /*----------------------------*/
2039 /*----------------------------*/
2041 /* if local & not passed as parameter &
2042 not used to find the function then ok */
2043 if (sym->level && !astHasSymbol (pbody->right, sym) &&
2044 !astHasSymbol (pbody->left, sym))
2050 /*------------------------------------------------------------------*/
2051 /*----------------------------*/
2052 /* return statement */
2053 /*----------------------------*/
2058 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
2063 if (astHasSymbol (pbody->left, sym))
2070 return isConformingBody (pbody->left, sym, body) &&
2071 isConformingBody (pbody->right, sym, body);
2074 /*-----------------------------------------------------------------*/
2075 /* isLoopReversible - takes a for loop as input && returns true */
2076 /* if the for loop is reversible. If yes will set the value of */
2077 /* the loop control var & init value & termination value */
2078 /*-----------------------------------------------------------------*/
2080 isLoopReversible (ast * loop, symbol ** loopCntrl,
2081 ast ** init, ast ** end)
2083 /* if option says don't do it then don't */
2084 if (optimize.noLoopReverse)
2086 /* there are several tests to determine this */
2088 /* for loop has to be of the form
2089 for ( <sym> = <const1> ;
2090 [<sym> < <const2>] ;
2091 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2093 if (!isLoopCountable (AST_FOR (loop, initExpr),
2094 AST_FOR (loop, condExpr),
2095 AST_FOR (loop, loopExpr),
2096 loopCntrl, init, end))
2099 /* now do some serious checking on the body of the loop
2102 return isConformingBody (loop->left, *loopCntrl, loop->left);
2106 /*-----------------------------------------------------------------*/
2107 /* replLoopSym - replace the loop sym by loop sym -1 */
2108 /*-----------------------------------------------------------------*/
2110 replLoopSym (ast * body, symbol * sym)
2113 if (!body || IS_AST_LINK (body))
2116 if (IS_AST_SYM_VALUE (body))
2119 if (isSymbolEqual (AST_SYMBOL (body), sym))
2123 body->opval.op = '-';
2124 body->left = newAst_VALUE (symbolVal (sym));
2125 body->right = newAst_VALUE (constCharVal (1));
2133 replLoopSym (body->left, sym);
2134 replLoopSym (body->right, sym);
2138 /*-----------------------------------------------------------------*/
2139 /* reverseLoop - do the actual loop reversal */
2140 /*-----------------------------------------------------------------*/
2142 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2146 /* create the following tree
2151 if (sym) goto for_continue ;
2154 /* put it together piece by piece */
2155 rloop = newNode (NULLOP,
2156 createIf (newAst_VALUE (symbolVal (sym)),
2158 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2161 newAst_VALUE (symbolVal (sym)),
2164 replLoopSym (loop->left, sym);
2165 setAstFileLine (rloop, init->filename, init->lineno);
2167 rloop = newNode (NULLOP,
2169 newAst_VALUE (symbolVal (sym)),
2170 newNode ('-', end, init)),
2171 createLabel (AST_FOR (loop, continueLabel),
2175 newNode (SUB_ASSIGN,
2176 newAst_VALUE (symbolVal (sym)),
2177 newAst_VALUE (constCharVal (1))),
2180 rloop->lineno=init->lineno;
2181 return decorateType (rloop, RESULT_TYPE_NONE);
2185 /*-----------------------------------------------------------------*/
2186 /* searchLitOp - search tree (*ops only) for an ast with literal */
2187 /*-----------------------------------------------------------------*/
2189 searchLitOp (ast *tree, ast **parent, const char *ops)
2193 if (tree && optimize.global_cse)
2195 /* is there a literal operand? */
2197 IS_AST_OP(tree->right) &&
2198 tree->right->right &&
2199 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2201 if (IS_LITERAL (RTYPE (tree->right)) !=
2202 IS_LITERAL (LTYPE (tree->right)))
2204 tree->right->decorated = 0;
2205 tree->decorated = 0;
2209 ret = searchLitOp (tree->right, parent, ops);
2214 IS_AST_OP(tree->left) &&
2215 tree->left->right &&
2216 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2218 if (IS_LITERAL (RTYPE (tree->left)) !=
2219 IS_LITERAL (LTYPE (tree->left)))
2221 tree->left->decorated = 0;
2222 tree->decorated = 0;
2226 ret = searchLitOp (tree->left, parent, ops);
2234 /*-----------------------------------------------------------------*/
2235 /* getResultFromType */
2236 /*-----------------------------------------------------------------*/
2238 getResultTypeFromType (sym_link *type)
2240 /* type = getSpec (type); */
2242 return RESULT_TYPE_BIT;
2243 if (IS_BITFIELD (type))
2245 int blen = SPEC_BLEN (type);
2248 return RESULT_TYPE_BIT;
2250 return RESULT_TYPE_CHAR;
2251 return RESULT_TYPE_INT;
2254 return RESULT_TYPE_CHAR;
2255 if (IS_INT (type) && !IS_LONG (type))
2256 return RESULT_TYPE_INT;
2257 return RESULT_TYPE_OTHER;
2260 /*-----------------------------------------------------------------*/
2261 /* addCast - adds casts to a type specified by RESULT_TYPE */
2262 /*-----------------------------------------------------------------*/
2264 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2267 bool upCasted = FALSE;
2271 case RESULT_TYPE_NONE:
2272 /* if thing smaller than int must be promoted to int */
2274 getSize (tree->etype) >= INTSIZE)
2275 /* promotion not necessary or already an int */
2277 /* char and bits: promote to int */
2278 newLink = newIntLink();
2281 case RESULT_TYPE_BIT:
2283 /* already an int */
2284 bitsForType (tree->etype) >= 16 ||
2285 /* bit to bit operation: don't promote, the code generators
2286 hopefully know everything about promotion rules */
2287 bitsForType (tree->etype) == 1)
2289 newLink = newIntLink();
2292 case RESULT_TYPE_CHAR:
2293 if (IS_CHAR (tree->etype) ||
2294 IS_FLOAT(tree->etype) ||
2295 IS_FIXED(tree->etype))
2297 newLink = newCharLink();
2299 case RESULT_TYPE_INT:
2301 if (getSize (tree->etype) > INTSIZE)
2303 /* warn ("Loosing significant digits"); */
2307 /* char: promote to int */
2309 getSize (tree->etype) >= INTSIZE)
2311 newLink = newIntLink();
2314 case RESULT_TYPE_IFX:
2315 case RESULT_TYPE_OTHER:
2317 /* return type is ifx, long, float: promote char to int */
2318 getSize (tree->etype) >= INTSIZE)
2320 newLink = newIntLink();
2326 tree->decorated = 0;
2327 tree = newNode (CAST, newAst_LINK (newLink), tree);
2328 tree->filename = tree->right->filename;
2329 tree->lineno = tree->right->lineno;
2330 /* keep unsigned type during cast to smaller type,
2331 but not when promoting from char to int */
2333 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2334 return decorateType (tree, resultType);
2337 /*-----------------------------------------------------------------*/
2338 /* resultTypePropagate - decides if resultType can be propagated */
2339 /*-----------------------------------------------------------------*/
2341 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2343 switch (tree->opval.op)
2360 if ((IS_AST_VALUE (tree->left) && !IS_INTEGRAL (tree->left->opval.val->etype)) ||
2361 (IS_AST_VALUE (tree->right) && !IS_INTEGRAL (tree->right->opval.val->etype)))
2362 return RESULT_TYPE_NONE;
2367 return RESULT_TYPE_NONE;
2371 return RESULT_TYPE_IFX;
2373 return RESULT_TYPE_NONE;
2377 /*-----------------------------------------------------------------*/
2378 /* getLeftResultType - gets type from left branch for propagation */
2379 /*-----------------------------------------------------------------*/
2381 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2383 switch (tree->opval.op)
2387 if (IS_PTR (LTYPE (tree)))
2388 return RESULT_TYPE_NONE;
2390 return getResultTypeFromType (LETYPE (tree));
2392 if (IS_PTR (currFunc->type->next))
2393 return RESULT_TYPE_NONE;
2395 return getResultTypeFromType (currFunc->type->next);
2397 if (!IS_ARRAY (LTYPE (tree)))
2399 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2400 return RESULT_TYPE_CHAR;
2407 /*------------------------------------------------------------------*/
2408 /* gatherImplicitVariables: assigns correct type information to */
2409 /* symbols and values created by replaceAstWithTemporary */
2410 /* and adds the symbols to the declarations list of the */
2411 /* innermost block that contains them */
2412 /*------------------------------------------------------------------*/
2414 gatherImplicitVariables (ast * tree, ast * block)
2419 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2421 /* keep track of containing scope */
2424 if (tree->type == EX_OP && tree->opval.op == '=' &&
2425 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2427 symbol *assignee = tree->left->opval.val->sym;
2429 /* special case for assignment to compiler-generated temporary variable:
2430 compute type of RHS, and set the symbol's type to match */
2431 if (assignee->type == NULL && assignee->infertype) {
2432 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2434 if (dtr != tree->right)
2437 assignee->type = copyLinkChain(TTYPE(dtr));
2438 assignee->etype = getSpec(assignee->type);
2439 SPEC_SCLS (assignee->etype) = S_AUTO;
2440 SPEC_OCLS (assignee->etype) = NULL;
2441 SPEC_EXTR (assignee->etype) = 0;
2442 SPEC_STAT (assignee->etype) = 0;
2443 SPEC_VOLATILE (assignee->etype) = 0;
2444 SPEC_ABSA (assignee->etype) = 0;
2446 wassertl(block != NULL, "implicit variable not contained in block");
2447 wassert(assignee->next == NULL);
2448 if (block != NULL) {
2449 symbol **decl = &(block->values.sym);
2452 wassert(*decl != assignee); /* should not already be in list */
2453 decl = &( (*decl)->next );
2460 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2461 tree->opval.val->type == NULL &&
2462 tree->opval.val->sym &&
2463 tree->opval.val->sym->infertype)
2465 /* fixup type of value for compiler-inferred temporary var */
2466 tree->opval.val->type = tree->opval.val->sym->type;
2467 tree->opval.val->etype = tree->opval.val->sym->etype;
2470 gatherImplicitVariables(tree->left, block);
2471 gatherImplicitVariables(tree->right, block);
2474 /*--------------------------------------------------------------------*/
2475 /* decorateType - compute type for this tree, also does type checking.*/
2476 /* This is done bottom up, since type has to flow upwards. */
2477 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2478 /* result is a char and the operand(s) are int's. */
2479 /* It also does constant folding, and parameter checking. */
2480 /*--------------------------------------------------------------------*/
2482 decorateType (ast * tree, RESULT_TYPE resultType)
2486 RESULT_TYPE resultTypeProp;
2491 /* if already has type then do nothing */
2492 if (tree->decorated)
2495 tree->decorated = 1;
2498 /* print the line */
2499 /* if not block & function */
2500 if (tree->type == EX_OP &&
2501 (tree->opval.op != FUNCTION &&
2502 tree->opval.op != BLOCK &&
2503 tree->opval.op != NULLOP))
2505 filename = tree->filename;
2506 lineno = tree->lineno;
2510 /* if any child is an error | this one is an error do nothing */
2511 if (tree->isError ||
2512 (tree->left && tree->left->isError) ||
2513 (tree->right && tree->right->isError))
2516 /*------------------------------------------------------------------*/
2517 /*----------------------------*/
2518 /* leaf has been reached */
2519 /*----------------------------*/
2520 filename = tree->filename;
2521 lineno = tree->lineno;
2522 /* if this is of type value */
2523 /* just get the type */
2524 if (tree->type == EX_VALUE)
2526 if (IS_LITERAL (tree->opval.val->etype))
2528 /* if this is a character array then declare it */
2529 if (IS_ARRAY (tree->opval.val->type))
2530 tree->opval.val = stringToSymbol (tree->opval.val);
2532 /* otherwise just copy the type information */
2533 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2537 if (tree->opval.val->sym)
2539 /* if the undefined flag is set then give error message */
2540 if (tree->opval.val->sym->undefined)
2542 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2544 TTYPE (tree) = TETYPE (tree) =
2545 tree->opval.val->type = tree->opval.val->sym->type =
2546 tree->opval.val->etype = tree->opval.val->sym->etype =
2547 copyLinkChain (INTTYPE);
2549 else if (tree->opval.val->sym->implicit)
2551 /* if implicit i.e. struct/union member then no type */
2552 TTYPE (tree) = TETYPE (tree) = NULL;
2556 /* copy the type from the value into the ast */
2557 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2559 /* and mark the symbol as referenced */
2560 tree->opval.val->sym->isref = 1;
2564 wassert(0); /* unreached: all values are literals or symbols */
2569 /* if type link for the case of cast */
2570 if (tree->type == EX_LINK)
2572 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2580 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2582 if (tree->left && tree->left->type == EX_OPERAND
2583 && (tree->left->opval.op == INC_OP
2584 || tree->left->opval.op == DEC_OP)
2585 && tree->left->left)
2587 tree->left->right = tree->left->left;
2588 tree->left->left = NULL;
2590 if (tree->right && tree->right->type == EX_OPERAND
2591 && (tree->right->opval.op == INC_OP
2592 || tree->right->opval.op == DEC_OP)
2593 && tree->right->left)
2595 tree->right->right = tree->right->left;
2596 tree->right->left = NULL;
2601 /* Before decorating the left branch we've to decide in dependence
2602 upon tree->opval.op, if resultType can be propagated */
2603 resultTypeProp = resultTypePropagate (tree, resultType);
2605 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2606 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2608 dtl = decorateType (tree->left, resultTypeProp);
2610 /* if an array node, we may need to swap branches */
2611 if (tree->opval.op == '[')
2613 /* determine which is the array & which the index */
2614 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2615 IS_INTEGRAL (LTYPE (tree)))
2617 ast *tempTree = tree->left;
2618 tree->left = tree->right;
2619 tree->right = tempTree;
2623 /* After decorating the left branch there's type information available
2624 in tree->left->?type. If the op is e.g. '=' we extract the type
2625 information from there and propagate it to the right branch. */
2626 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2628 switch (tree->opval.op)
2631 /* delay right side for '?' operator since conditional macro
2632 expansions might rely on this */
2636 /* decorate right side for CALL (parameter list) in processParms();
2637 there is resultType available */
2641 /* don't allocate string if it is a sizeof argument */
2643 dtr = decorateType (tree->right, resultTypeProp);
2647 dtr = decorateType (tree->right, resultTypeProp);
2651 /* this is to take care of situations
2652 when the tree gets rewritten */
2653 if (dtl != tree->left)
2655 if (dtr != tree->right)
2657 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2661 /* depending on type of operator do */
2663 switch (tree->opval.op)
2665 /*------------------------------------------------------------------*/
2666 /*----------------------------*/
2668 /*----------------------------*/
2671 /* first check if this is a array or a pointer */
2672 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2674 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2675 goto errorTreeReturn;
2678 /* check if the type of the idx */
2679 if (!IS_INTEGRAL (RTYPE (tree)))
2681 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2682 goto errorTreeReturn;
2685 /* if the left is an rvalue then error */
2688 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2689 goto errorTreeReturn;
2692 if (IS_LITERAL (RTYPE (tree)))
2694 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2695 int arraySize = DCL_ELEM (LTYPE (tree));
2696 if (arraySize && arrayIndex >= arraySize)
2698 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2703 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2704 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2707 /*------------------------------------------------------------------*/
2708 /*----------------------------*/
2710 /*----------------------------*/
2712 /* if this is not a structure */
2713 if (!IS_STRUCT (LTYPE (tree)))
2715 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2716 goto errorTreeReturn;
2718 TTYPE (tree) = structElemType (LTYPE (tree),
2719 (tree->right->type == EX_VALUE ?
2720 tree->right->opval.val : NULL));
2721 TETYPE (tree) = getSpec (TTYPE (tree));
2724 /*------------------------------------------------------------------*/
2725 /*----------------------------*/
2726 /* struct/union pointer */
2727 /*----------------------------*/
2729 /* if not pointer to a structure */
2730 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2732 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2733 goto errorTreeReturn;
2736 if (!IS_STRUCT (LTYPE (tree)->next))
2738 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2739 goto errorTreeReturn;
2742 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2743 (tree->right->type == EX_VALUE ?
2744 tree->right->opval.val : NULL));
2745 TETYPE (tree) = getSpec (TTYPE (tree));
2747 /* adjust the storage class */
2748 switch (DCL_TYPE(tree->left->ftype)) {
2750 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2753 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2756 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2759 SPEC_SCLS (TETYPE (tree)) = 0;
2762 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2765 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2768 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2771 SPEC_SCLS (TETYPE (tree)) = 0;
2778 /* This breaks with extern declarations, bitfields, and perhaps other */
2779 /* cases (gcse). Let's leave this optimization disabled for now and */
2780 /* ponder if there's a safe way to do this. -- EEP */
2782 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2783 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2785 /* If defined struct type at addr var
2786 then rewrite (&struct var)->member
2788 and define membertype at (addr+offsetof(struct var,member)) temp
2791 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2792 AST_SYMBOL(tree->right));
2794 sym = newSymbol(genSymName (0), 0);
2795 sym->type = TTYPE (tree);
2796 sym->etype = getSpec(sym->type);
2797 sym->lineDef = tree->lineno;
2800 SPEC_STAT (sym->etype) = 1;
2801 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2803 SPEC_ABSA(sym->etype) = 1;
2804 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2807 AST_VALUE (tree) = symbolVal(sym);
2810 tree->type = EX_VALUE;
2818 /*------------------------------------------------------------------*/
2819 /*----------------------------*/
2820 /* ++/-- operation */
2821 /*----------------------------*/
2825 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2826 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2827 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2828 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2837 /*------------------------------------------------------------------*/
2838 /*----------------------------*/
2840 /*----------------------------*/
2841 case '&': /* can be unary */
2842 /* if right is NULL then unary operation */
2843 if (tree->right) /* not an unary operation */
2846 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2848 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2849 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2850 printTypeChain (LTYPE (tree), stderr);
2851 fprintf (stderr, ",");
2852 printTypeChain (RTYPE (tree), stderr);
2853 fprintf (stderr, "\n");
2854 goto errorTreeReturn;
2857 /* if they are both literal */
2858 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2860 tree->type = EX_VALUE;
2861 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2862 valFromType (RETYPE (tree)), '&');
2864 tree->right = tree->left = NULL;
2865 TETYPE (tree) = tree->opval.val->etype;
2866 TTYPE (tree) = tree->opval.val->type;
2870 /* see if this is a GETHBIT operation if yes
2873 ast *otree = optimizeGetHbit (tree, resultType);
2876 return decorateType (otree, RESULT_TYPE_NONE);
2879 /* see if this is a GETABIT operation if yes
2882 ast *otree = optimizeGetAbit (tree, resultType);
2885 return decorateType (otree, RESULT_TYPE_NONE);
2888 /* see if this is a GETBYTE operation if yes
2891 ast *otree = optimizeGetByte (tree, resultType);
2894 return decorateType (otree, RESULT_TYPE_NONE);
2897 /* see if this is a GETWORD operation if yes
2900 ast *otree = optimizeGetWord (tree, resultType);
2903 return decorateType (otree, RESULT_TYPE_NONE);
2906 /* if left is a literal exchange left & right */
2907 if (IS_LITERAL (LTYPE (tree)))
2909 ast *tTree = tree->left;
2910 tree->left = tree->right;
2911 tree->right = tTree;
2914 /* if right is a literal and */
2915 /* we can find a 2nd literal in an and-tree then */
2916 /* rearrange the tree */
2917 if (IS_LITERAL (RTYPE (tree)))
2920 ast *litTree = searchLitOp (tree, &parent, "&");
2924 ast *tTree = litTree->left;
2925 litTree->left = tree->right;
2926 tree->right = tTree;
2927 /* both operands in litTree are literal now */
2928 decorateType (parent, resultType);
2932 LRVAL (tree) = RRVAL (tree) = 1;
2934 TTYPE (tree) = computeType (LTYPE (tree),
2938 TETYPE (tree) = getSpec (TTYPE (tree));
2943 /*------------------------------------------------------------------*/
2944 /*----------------------------*/
2946 /*----------------------------*/
2947 p = newLink (DECLARATOR);
2948 /* if bit field then error */
2949 if (IS_BITVAR (tree->left->etype))
2951 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2952 goto errorTreeReturn;
2955 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2957 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2958 goto errorTreeReturn;
2961 if (IS_FUNC (LTYPE (tree)))
2963 // this ought to be ignored
2964 return (tree->left);
2967 if (IS_LITERAL(LTYPE(tree)))
2969 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2970 goto errorTreeReturn;
2975 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2976 goto errorTreeReturn;
2979 DCL_TYPE (p) = POINTER;
2980 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2981 DCL_TYPE (p) = CPOINTER;
2982 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2983 DCL_TYPE (p) = FPOINTER;
2984 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2985 DCL_TYPE (p) = PPOINTER;
2986 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2987 DCL_TYPE (p) = IPOINTER;
2988 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2989 DCL_TYPE (p) = EEPPOINTER;
2990 else if (SPEC_OCLS(tree->left->etype))
2991 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2993 DCL_TYPE (p) = POINTER;
2995 if (IS_AST_SYM_VALUE (tree->left))
2997 AST_SYMBOL (tree->left)->addrtaken = 1;
2998 AST_SYMBOL (tree->left)->allocreq = 1;
3001 p->next = LTYPE (tree);
3003 TETYPE (tree) = getSpec (TTYPE (tree));
3008 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
3009 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
3011 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
3012 AST_SYMBOL(tree->left->right));
3013 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
3014 valueFromLit(element->offset));
3017 tree->type = EX_VALUE;
3018 tree->values.literalFromCast = 1;
3024 /*------------------------------------------------------------------*/
3025 /*----------------------------*/
3027 /*----------------------------*/
3029 /* if the rewrite succeeds then don't go any further */
3031 ast *wtree = optimizeRRCRLC (tree);
3033 return decorateType (wtree, RESULT_TYPE_NONE);
3035 wtree = optimizeSWAP (tree);
3037 return decorateType (wtree, RESULT_TYPE_NONE);
3040 /* if left is a literal exchange left & right */
3041 if (IS_LITERAL (LTYPE (tree)))
3043 ast *tTree = tree->left;
3044 tree->left = tree->right;
3045 tree->right = tTree;
3048 /* if right is a literal and */
3049 /* we can find a 2nd literal in an or-tree then */
3050 /* rearrange the tree */
3051 if (IS_LITERAL (RTYPE (tree)))
3054 ast *litTree = searchLitOp (tree, &parent, "|");
3058 ast *tTree = litTree->left;
3059 litTree->left = tree->right;
3060 tree->right = tTree;
3061 /* both operands in tTree are literal now */
3062 decorateType (parent, resultType);
3067 /*------------------------------------------------------------------*/
3068 /*----------------------------*/
3070 /*----------------------------*/
3072 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3074 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3075 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3076 printTypeChain (LTYPE (tree), stderr);
3077 fprintf (stderr, ",");
3078 printTypeChain (RTYPE (tree), stderr);
3079 fprintf (stderr, "\n");
3080 goto errorTreeReturn;
3083 /* if they are both literal then rewrite the tree */
3084 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3086 tree->type = EX_VALUE;
3087 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3088 valFromType (RETYPE (tree)),
3090 tree->right = tree->left = NULL;
3091 TETYPE (tree) = tree->opval.val->etype;
3092 TTYPE (tree) = tree->opval.val->type;
3096 /* if left is a literal exchange left & right */
3097 if (IS_LITERAL (LTYPE (tree)))
3099 ast *tTree = tree->left;
3100 tree->left = tree->right;
3101 tree->right = tTree;
3104 /* if right is a literal and */
3105 /* we can find a 2nd literal in a xor-tree then */
3106 /* rearrange the tree */
3107 if (IS_LITERAL (RTYPE (tree)) &&
3108 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3111 ast *litTree = searchLitOp (tree, &parent, "^");
3115 ast *tTree = litTree->left;
3116 litTree->left = tree->right;
3117 tree->right = tTree;
3118 /* both operands in litTree are literal now */
3119 decorateType (parent, resultType);
3123 LRVAL (tree) = RRVAL (tree) = 1;
3125 TTYPE (tree) = computeType (LTYPE (tree),
3129 TETYPE (tree) = getSpec (TTYPE (tree));
3133 /*------------------------------------------------------------------*/
3134 /*----------------------------*/
3136 /*----------------------------*/
3138 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3140 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3141 goto errorTreeReturn;
3143 /* if they are both literal then */
3144 /* rewrite the tree */
3145 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3147 tree->type = EX_VALUE;
3148 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3149 valFromType (RETYPE (tree)));
3150 tree->right = tree->left = NULL;
3151 TETYPE (tree) = getSpec (TTYPE (tree) =
3152 tree->opval.val->type);
3156 LRVAL (tree) = RRVAL (tree) = 1;
3158 TETYPE (tree) = getSpec (TTYPE (tree) =
3159 computeType (LTYPE (tree),
3164 /* if right is a literal and */
3165 /* left is also a division by a literal then */
3166 /* rearrange the tree */
3167 if (IS_LITERAL (RTYPE (tree))
3168 /* avoid infinite loop */
3169 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3172 ast *litTree = searchLitOp (tree, &parent, "/");
3175 if (IS_LITERAL (RTYPE (litTree)))
3179 litTree->right = newNode ('*',
3181 copyAst (tree->right));
3182 litTree->right->filename = tree->filename;
3183 litTree->right->lineno = tree->lineno;
3185 tree->right->opval.val = constCharVal (1);
3186 decorateType (parent, resultType);
3190 /* litTree->left is literal: no gcse possible.
3191 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3192 this would cause an infinit loop. */
3193 parent->decorated = 1;
3194 decorateType (litTree, resultType);
3201 /*------------------------------------------------------------------*/
3202 /*----------------------------*/
3204 /*----------------------------*/
3206 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3208 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3209 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3210 printTypeChain (LTYPE (tree), stderr);
3211 fprintf (stderr, ",");
3212 printTypeChain (RTYPE (tree), stderr);
3213 fprintf (stderr, "\n");
3214 goto errorTreeReturn;
3216 /* if they are both literal then */
3217 /* rewrite the tree */
3218 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3220 tree->type = EX_VALUE;
3221 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3222 valFromType (RETYPE (tree)));
3223 tree->right = tree->left = NULL;
3224 TETYPE (tree) = getSpec (TTYPE (tree) =
3225 tree->opval.val->type);
3228 LRVAL (tree) = RRVAL (tree) = 1;
3229 TETYPE (tree) = getSpec (TTYPE (tree) =
3230 computeType (LTYPE (tree),
3236 /*------------------------------------------------------------------*/
3237 /*----------------------------*/
3238 /* address dereference */
3239 /*----------------------------*/
3240 case '*': /* can be unary : if right is null then unary operation */
3243 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3245 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3246 goto errorTreeReturn;
3251 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3252 goto errorTreeReturn;
3254 if (IS_ADDRESS_OF_OP (tree->left))
3256 /* replace *&obj with obj */
3257 return tree->left->left;
3259 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3260 TETYPE (tree) = getSpec (TTYPE (tree));
3261 /* adjust the storage class */
3262 switch (DCL_TYPE(tree->left->ftype)) {
3264 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3267 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3270 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3273 SPEC_SCLS (TETYPE (tree)) = 0;
3276 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3279 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3282 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3285 SPEC_SCLS (TETYPE (tree)) = 0;
3294 /*------------------------------------------------------------------*/
3295 /*----------------------------*/
3296 /* multiplication */
3297 /*----------------------------*/
3298 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3300 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3301 goto errorTreeReturn;
3304 /* if they are both literal then */
3305 /* rewrite the tree */
3306 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3308 tree->type = EX_VALUE;
3309 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3310 valFromType (RETYPE (tree)));
3311 tree->right = tree->left = NULL;
3312 TETYPE (tree) = getSpec (TTYPE (tree) =
3313 tree->opval.val->type);
3317 /* if left is a literal exchange left & right */
3318 if (IS_LITERAL (LTYPE (tree)))
3320 ast *tTree = tree->left;
3321 tree->left = tree->right;
3322 tree->right = tTree;
3325 /* if right is a literal and */
3326 /* we can find a 2nd literal in a mul-tree then */
3327 /* rearrange the tree */
3328 if (IS_LITERAL (RTYPE (tree)))
3331 ast *litTree = searchLitOp (tree, &parent, "*");
3335 ast *tTree = litTree->left;
3336 litTree->left = tree->right;
3337 tree->right = tTree;
3338 /* both operands in litTree are literal now */
3339 decorateType (parent, resultType);
3343 LRVAL (tree) = RRVAL (tree) = 1;
3344 tree->left = addCast (tree->left, resultTypeProp, FALSE);
3345 tree->right = addCast (tree->right, resultTypeProp, FALSE);
3346 TETYPE (tree) = getSpec (TTYPE (tree) =
3347 computeType (LTYPE (tree),
3354 /*------------------------------------------------------------------*/
3355 /*----------------------------*/
3356 /* unary '+' operator */
3357 /*----------------------------*/
3362 if (!IS_ARITHMETIC (LTYPE (tree)))
3364 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3365 goto errorTreeReturn;
3368 /* if left is a literal then do it */
3369 if (IS_LITERAL (LTYPE (tree)))
3371 tree->type = EX_VALUE;
3372 tree->opval.val = valFromType (LETYPE (tree));
3374 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3378 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3382 /*------------------------------------------------------------------*/
3383 /*----------------------------*/
3385 /*----------------------------*/
3387 /* this is not a unary operation */
3388 /* if both pointers then problem */
3389 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3390 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3392 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3393 goto errorTreeReturn;
3396 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3397 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3399 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3400 goto errorTreeReturn;
3403 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3404 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3406 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3407 goto errorTreeReturn;
3409 /* if they are both literal then */
3410 /* rewrite the tree */
3411 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3413 tree->type = EX_VALUE;
3414 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3415 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3416 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3417 valFromType (RETYPE (tree)));
3418 tree->right = tree->left = NULL;
3419 TETYPE (tree) = getSpec (TTYPE (tree) =
3420 tree->opval.val->type);
3424 /* if the right is a pointer or left is a literal
3425 xchange left & right */
3426 if (IS_ARRAY (RTYPE (tree)) ||
3427 IS_PTR (RTYPE (tree)) ||
3428 IS_LITERAL (LTYPE (tree)))
3430 ast *tTree = tree->left;
3431 tree->left = tree->right;
3432 tree->right = tTree;
3435 /* if right is a literal and */
3436 /* left is also an addition/subtraction with a literal then */
3437 /* rearrange the tree */
3438 if (IS_LITERAL (RTYPE (tree)))
3440 ast *litTree, *parent;
3441 litTree = searchLitOp (tree, &parent, "+-");
3444 if (litTree->opval.op == '+')
3448 ast *tTree = litTree->left;
3449 litTree->left = tree->right;
3450 tree->right = tree->left;
3453 else if (litTree->opval.op == '-')
3455 if (IS_LITERAL (RTYPE (litTree)))
3459 ast *tTree = litTree->left;
3460 litTree->left = tree->right;
3461 tree->right = tTree;
3467 ast *tTree = litTree->right;
3468 litTree->right = tree->right;
3469 tree->right = tTree;
3470 litTree->opval.op = '+';
3471 tree->opval.op = '-';
3474 decorateType (parent, resultType);
3478 LRVAL (tree) = RRVAL (tree) = 1;
3479 /* if the left is a pointer */
3480 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3481 TETYPE (tree) = getSpec (TTYPE (tree) =
3485 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3486 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3487 TETYPE (tree) = getSpec (TTYPE (tree) =
3488 computeType (LTYPE (tree),
3496 /*------------------------------------------------------------------*/
3497 /*----------------------------*/
3499 /*----------------------------*/
3500 case '-': /* can be unary */
3501 /* if right is null then unary */
3505 if (!IS_ARITHMETIC (LTYPE (tree)))
3507 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3508 goto errorTreeReturn;
3511 /* if left is a literal then do it */
3512 if (IS_LITERAL (LTYPE (tree)))
3514 tree->type = EX_VALUE;
3515 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3517 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3520 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3521 TETYPE (tree) = getSpec (TTYPE (tree) =
3522 computeType (LTYPE (tree),
3530 /*------------------------------------------------------------------*/
3531 /*----------------------------*/
3533 /*----------------------------*/
3535 if (!(IS_PTR (LTYPE (tree)) ||
3536 IS_ARRAY (LTYPE (tree)) ||
3537 IS_ARITHMETIC (LTYPE (tree))))
3539 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3540 goto errorTreeReturn;
3543 if (!(IS_PTR (RTYPE (tree)) ||
3544 IS_ARRAY (RTYPE (tree)) ||
3545 IS_ARITHMETIC (RTYPE (tree))))
3547 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3548 goto errorTreeReturn;
3551 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3552 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3553 IS_INTEGRAL (RTYPE (tree))))
3555 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3556 goto errorTreeReturn;
3559 /* if they are both literal then */
3560 /* rewrite the tree */
3561 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3563 tree->type = EX_VALUE;
3564 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3565 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3566 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3567 valFromType (RETYPE (tree)));
3568 tree->right = tree->left = NULL;
3569 TETYPE (tree) = getSpec (TTYPE (tree) =
3570 tree->opval.val->type);
3574 /* if the left & right are equal then zero */
3575 if (isAstEqual (tree->left, tree->right))
3577 tree->type = EX_VALUE;
3578 tree->left = tree->right = NULL;
3579 tree->opval.val = constCharVal (0);
3580 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3584 /* if both of them are pointers or arrays then */
3585 /* the result is going to be an integer */
3586 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3587 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3588 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3590 /* if only the left is a pointer */
3591 /* then result is a pointer */
3592 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3593 TETYPE (tree) = getSpec (TTYPE (tree) =
3597 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3598 tree->right = addCast (tree->right, resultTypeProp, TRUE);
3600 TETYPE (tree) = getSpec (TTYPE (tree) =
3601 computeType (LTYPE (tree),
3607 LRVAL (tree) = RRVAL (tree) = 1;
3609 /* if right is a literal and */
3610 /* left is also an addition/subtraction with a literal then */
3611 /* rearrange the tree */
3612 if (IS_LITERAL (RTYPE (tree))
3613 /* avoid infinite loop */
3614 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3616 ast *litTree, *litParent;
3617 litTree = searchLitOp (tree, &litParent, "+-");
3620 if (litTree->opval.op == '+')
3624 ast *tTree = litTree->left;
3625 litTree->left = litTree->right;
3626 litTree->right = tree->right;
3627 tree->right = tTree;
3628 tree->opval.op = '+';
3629 litTree->opval.op = '-';
3631 else if (litTree->opval.op == '-')
3633 if (IS_LITERAL (RTYPE (litTree)))
3637 ast *tTree = litTree->left;
3638 litTree->left = tree->right;
3639 tree->right = litParent->left;
3640 litParent->left = tTree;
3641 litTree->opval.op = '+';
3643 tree->decorated = 0;
3644 decorateType (tree, resultType);
3650 ast *tTree = litTree->right;
3651 litTree->right = tree->right;
3652 tree->right = tTree;
3655 decorateType (litParent, resultType);
3660 /*------------------------------------------------------------------*/
3661 /*----------------------------*/
3663 /*----------------------------*/
3665 /* can be only integral type */
3666 if (!IS_INTEGRAL (LTYPE (tree)))
3668 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3669 goto errorTreeReturn;
3672 /* if left is a literal then do it */
3673 if (IS_LITERAL (LTYPE (tree)))
3675 tree->type = EX_VALUE;
3676 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3678 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3679 return addCast (tree, resultTypeProp, TRUE);
3682 if (resultType == RESULT_TYPE_BIT &&
3683 IS_UNSIGNED (tree->left->etype) &&
3684 getSize (tree->left->etype) < INTSIZE)
3686 /* promotion rules are responsible for this strange result:
3687 bit -> int -> ~int -> bit
3688 uchar -> int -> ~int -> bit
3690 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3692 /* optimize bit-result, even if we optimize a buggy source */
3693 tree->type = EX_VALUE;
3694 tree->opval.val = constCharVal (1);
3697 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3699 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3702 /*------------------------------------------------------------------*/
3703 /*----------------------------*/
3705 /*----------------------------*/
3707 /* can be pointer */
3708 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3709 !IS_PTR (LTYPE (tree)) &&
3710 !IS_ARRAY (LTYPE (tree)))
3712 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3713 goto errorTreeReturn;
3716 /* if left is another '!' */
3717 if (IS_AST_NOT_OPER (tree->left))
3719 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3721 /* replace double '!!X' by 'X' */
3722 return tree->left->left;
3724 /* remove double '!!X' by 'X ? 1 : 0' */
3725 tree->opval.op = '?';
3726 tree->left = tree->left->left;
3727 tree->right = newNode (':',
3728 newAst_VALUE (constCharVal (1)),
3729 newAst_VALUE (constCharVal (0)));
3730 tree->right->filename = tree->filename;
3731 tree->right->lineno = tree->lineno;
3732 tree->decorated = 0;
3733 return decorateType (tree, resultType);
3736 /* if left is a literal then do it */
3737 if (IS_LITERAL (LTYPE (tree)))
3739 tree->type = EX_VALUE;
3740 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3742 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3746 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3749 /*------------------------------------------------------------------*/
3750 /*----------------------------*/
3752 /*----------------------------*/
3756 TTYPE (tree) = LTYPE (tree);
3757 TETYPE (tree) = LETYPE (tree);
3762 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3766 TTYPE (tree) = TETYPE (tree) = newCharLink();
3770 TTYPE (tree) = TETYPE (tree) = newIntLink();
3775 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3777 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3778 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3779 printTypeChain (LTYPE (tree), stderr);
3780 fprintf (stderr, ",");
3781 printTypeChain (RTYPE (tree), stderr);
3782 fprintf (stderr, "\n");
3783 goto errorTreeReturn;
3786 /* make smaller type only if it's a LEFT_OP */
3787 if (tree->opval.op == LEFT_OP)
3788 tree->left = addCast (tree->left, resultTypeProp, TRUE);
3790 /* if they are both literal then */
3791 /* rewrite the tree */
3792 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3794 tree->type = EX_VALUE;
3795 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3796 valFromType (RETYPE (tree)),
3797 (tree->opval.op == LEFT_OP ? 1 : 0));
3798 tree->right = tree->left = NULL;
3799 TETYPE (tree) = getSpec (TTYPE (tree) =
3800 tree->opval.val->type);
3804 /* see if this is a GETBYTE operation if yes
3807 ast *otree = optimizeGetByte (tree, resultType);
3810 return decorateType (otree, RESULT_TYPE_NONE);
3813 /* see if this is a GETWORD operation if yes
3816 ast *otree = optimizeGetWord (tree, resultType);
3819 return decorateType (otree, RESULT_TYPE_NONE);
3822 LRVAL (tree) = RRVAL (tree) = 1;
3823 if (tree->opval.op == LEFT_OP)
3825 TETYPE (tree) = getSpec (TTYPE (tree) =
3826 computeType (LTYPE (tree),
3833 /* no promotion necessary */
3834 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3835 if (IS_LITERAL (TTYPE (tree)))
3836 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3839 /* if only the right side is a literal & we are
3840 shifting more than size of the left operand then zero */
3841 if (IS_LITERAL (RTYPE (tree)) &&
3842 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3843 (getSize (TETYPE (tree)) * 8))
3845 if (tree->opval.op==LEFT_OP ||
3846 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3848 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3849 (tree->opval.op == LEFT_OP ? "left" : "right"));
3850 tree->type = EX_VALUE;
3851 tree->left = tree->right = NULL;
3852 tree->opval.val = constCharVal (0);
3853 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3860 /*------------------------------------------------------------------*/
3861 /*----------------------------*/
3863 /*----------------------------*/
3864 case CAST: /* change the type */
3865 /* cannot cast to an aggregate type */
3866 if (IS_AGGREGATE (LTYPE (tree)))
3868 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3869 goto errorTreeReturn;
3872 /* make sure the type is complete and sane */
3873 changePointer(LTYPE(tree));
3874 checkTypeSanity(LETYPE(tree), "(cast)");
3876 /* if 'from' and 'to' are the same remove the superfluous cast,
3877 * this helps other optimizations */
3878 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3880 /* mark that the explicit cast has been removed,
3881 * for proper processing (no integer promotion) of explicitly typecasted variable arguments */
3882 tree->right->values.removedCast = 1;
3886 /* If code memory is read only, then pointers to code memory */
3887 /* implicitly point to constants -- make this explicit */
3889 sym_link *t = LTYPE(tree);
3890 while (t && t->next)
3892 if (IS_CODEPTR(t) && port->mem.code_ro)
3894 if (IS_SPEC(t->next))
3895 SPEC_CONST (t->next) = 1;
3897 DCL_PTR_CONST (t->next) = 1;
3904 /* if the right is a literal replace the tree */
3905 if (IS_LITERAL (RETYPE (tree)))
3907 if (!IS_PTR (LTYPE (tree)))
3909 tree->type = EX_VALUE;
3911 valCastLiteral (LTYPE (tree),
3912 floatFromVal (valFromType (RETYPE (tree))));
3915 TTYPE (tree) = tree->opval.val->type;
3916 tree->values.literalFromCast = 1;
3918 else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3919 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */
3921 sym_link *rest = LTYPE(tree)->next;
3922 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3923 TTYPE(tree) = newLink(DECLARATOR);
3924 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3925 TTYPE(tree)->next = rest;
3926 tree->left->opval.lnk = TTYPE(tree);
3931 TTYPE (tree) = LTYPE (tree);
3937 TTYPE (tree) = LTYPE (tree);
3941 #if 0 // this is already checked, now this could be explicit
3942 /* if pointer to struct then check names */
3943 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3944 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3945 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3947 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3948 SPEC_STRUCT(LETYPE(tree))->tag);
3951 if (IS_ADDRESS_OF_OP(tree->right)
3952 && IS_AST_SYM_VALUE (tree->right->left)
3953 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype))
3955 symbol * sym = AST_SYMBOL (tree->right->left);
3956 unsigned int gptype = 0;
3957 unsigned int addr = SPEC_ADDR (sym->etype);
3959 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE) || TARGET_IS_PIC16) )
3961 switch (SPEC_SCLS (sym->etype))
3964 gptype = GPTYPE_CODE;
3967 gptype = GPTYPE_FAR;
3971 gptype = GPTYPE_NEAR;
3974 gptype = GPTYPE_XSTACK;
3979 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3980 gptype = GPTYPE_NEAR;
3982 addr |= gptype << (8*(GPTRSIZE - 1));
3985 tree->type = EX_VALUE;
3986 tree->opval.val = valCastLiteral (LTYPE (tree), addr);
3987 TTYPE (tree) = tree->opval.val->type;
3988 TETYPE (tree) = getSpec (TTYPE (tree));
3991 tree->values.literalFromCast = 1;
3995 /* handle offsetof macro: */
3996 /* #define offsetof(TYPE, MEMBER) \ */
3997 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3998 if (IS_ADDRESS_OF_OP(tree->right)
3999 && IS_AST_OP (tree->right->left)
4000 && tree->right->left->opval.op == PTR_OP
4001 && IS_AST_OP (tree->right->left->left)
4002 && tree->right->left->left->opval.op == CAST
4003 && IS_AST_LIT_VALUE(tree->right->left->left->right))
4005 symbol *element = getStructElement (
4006 SPEC_STRUCT (LETYPE(tree->right->left)),
4007 AST_SYMBOL(tree->right->left->right)
4012 tree->type = EX_VALUE;
4013 tree->opval.val = valCastLiteral (
4016 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
4019 TTYPE (tree) = tree->opval.val->type;
4020 TETYPE (tree) = getSpec (TTYPE (tree));
4027 /* if the right is a literal replace the tree */
4028 if (IS_LITERAL (RETYPE (tree)))
4031 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) )
4033 /* rewrite (type *)litaddr
4035 and define type at litaddr temp
4036 (but only if type's storage class is not generic)
4038 ast *newTree = newNode ('&', NULL, NULL);
4041 TTYPE (newTree) = LTYPE (tree);
4042 TETYPE (newTree) = getSpec(LTYPE (tree));
4044 /* define a global symbol at the casted address*/
4045 sym = newSymbol(genSymName (0), 0);
4046 sym->type = LTYPE (tree)->next;
4048 sym->type = newLink (V_VOID);
4049 sym->etype = getSpec(sym->type);
4050 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
4051 sym->lineDef = tree->lineno;
4054 SPEC_STAT (sym->etype) = 1;
4055 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
4056 SPEC_ABSA(sym->etype) = 1;
4057 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
4060 newTree->left = newAst_VALUE(symbolVal(sym));
4061 newTree->left->filename = tree->filename;
4062 newTree->left->lineno = tree->lineno;
4063 LTYPE (newTree) = sym->type;
4064 LETYPE (newTree) = sym->etype;
4065 LLVAL (newTree) = 1;
4066 LRVAL (newTree) = 0;
4067 TLVAL (newTree) = 1;
4071 if (!IS_PTR (LTYPE (tree)))
4073 tree->type = EX_VALUE;
4075 valCastLiteral (LTYPE (tree), floatFromVal (valFromType (RTYPE (tree))));
4076 TTYPE (tree) = tree->opval.val->type;
4079 tree->values.literalFromCast = 1;
4080 TETYPE (tree) = getSpec (TTYPE (tree));
4084 if (IS_GENPTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)) && !IS_GENPTR (RTYPE (tree)) && (resultType != RESULT_TYPE_GPTR))
4086 DCL_TYPE (LTYPE (tree)) = DCL_TYPE (RTYPE (tree));
4088 TTYPE (tree) = LTYPE (tree);
4092 TETYPE (tree) = getSpec (TTYPE (tree));
4096 /*------------------------------------------------------------------*/
4097 /*----------------------------*/
4098 /* logical &&, || */
4099 /*----------------------------*/
4102 /* each must be arithmetic type or be a pointer */
4103 if (!IS_PTR (LTYPE (tree)) &&
4104 !IS_ARRAY (LTYPE (tree)) &&
4105 !IS_INTEGRAL (LTYPE (tree)))
4107 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4108 goto errorTreeReturn;
4111 if (!IS_PTR (RTYPE (tree)) &&
4112 !IS_ARRAY (RTYPE (tree)) &&
4113 !IS_INTEGRAL (RTYPE (tree)))
4115 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4116 goto errorTreeReturn;
4118 /* if they are both literal then */
4119 /* rewrite the tree */
4120 if (IS_LITERAL (RTYPE (tree)) &&
4121 IS_LITERAL (LTYPE (tree)))
4123 tree->type = EX_VALUE;
4124 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4125 valFromType (RTYPE (tree)),
4127 tree->right = tree->left = NULL;
4128 TETYPE (tree) = getSpec (TTYPE (tree) =
4129 tree->opval.val->type);
4132 LRVAL (tree) = RRVAL (tree) = 1;
4133 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4136 /*------------------------------------------------------------------*/
4137 /*----------------------------*/
4138 /* comparison operators */
4139 /*----------------------------*/
4147 ast *lt = optimizeCompare (tree);
4153 /* if they are pointers they must be castable */
4154 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4156 if (tree->opval.op==EQ_OP &&
4157 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4158 // we cannot cast a gptr to a !gptr: switch the leaves
4159 struct ast *s=tree->left;
4160 tree->left=tree->right;
4163 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4165 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4166 fprintf (stderr, "comparing type ");
4167 printTypeChain (LTYPE (tree), stderr);
4168 fprintf (stderr, "to type ");
4169 printTypeChain (RTYPE (tree), stderr);
4170 fprintf (stderr, "\n");
4171 goto errorTreeReturn;
4174 /* else they should be promotable to one another */
4177 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4178 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4180 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4182 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4183 fprintf (stderr, "comparing type ");
4184 printTypeChain (LTYPE (tree), stderr);
4185 fprintf (stderr, "to type ");
4186 printTypeChain (RTYPE (tree), stderr);
4187 fprintf (stderr, "\n");
4188 goto errorTreeReturn;
4193 CCR_RESULT ccr_result = CCR_OK;
4195 /* if left is integral and right is literal
4196 then check constant range */
4197 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4198 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4199 tree->opval.op, FALSE);
4200 if (ccr_result == CCR_OK &&
4201 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4202 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4203 tree->opval.op, TRUE);
4206 case CCR_ALWAYS_TRUE:
4207 case CCR_ALWAYS_FALSE:
4208 if (!options.lessPedantic)
4209 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4210 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4211 return decorateType (newAst_VALUE (constCharVal ((unsigned char)(ccr_result == CCR_ALWAYS_TRUE))), resultType);
4218 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4219 if (tree->opval.op == '>' &&
4220 SPEC_USIGN(LETYPE(tree)) &&
4221 IS_LITERAL(RTYPE(tree)) &&
4222 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4224 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4226 /* the parent is an ifx: */
4227 /* if (unsigned value) */
4231 /* (unsigned value) ? 1 : 0 */
4232 tree->opval.op = '?';
4233 tree->right = newNode (':',
4234 newAst_VALUE (constCharVal (1)),
4235 tree->right); /* val 0 */
4236 tree->right->filename = tree->filename;
4237 tree->right->lineno = tree->lineno;
4238 tree->right->left->filename = tree->filename;
4239 tree->right->left->lineno = tree->lineno;
4240 tree->decorated = 0;
4241 return decorateType (tree, resultType);
4244 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4245 if (IS_LITERAL(RTYPE(tree)) &&
4246 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4247 tree->opval.op == EQ_OP &&
4248 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4250 tree->opval.op = '!';
4252 tree->decorated = 0;
4253 return decorateType (tree, resultType);
4256 /* if they are both literal then */
4257 /* rewrite the tree */
4258 if (IS_LITERAL (RTYPE (tree)) &&
4259 IS_LITERAL (LTYPE (tree)))
4261 tree->type = EX_VALUE;
4262 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4263 valFromType (RETYPE (tree)),
4265 tree->right = tree->left = NULL;
4266 TETYPE (tree) = getSpec (TTYPE (tree) =
4267 tree->opval.val->type);
4271 /* if one is 'signed char ' and the other one is 'unsigned char' */
4272 /* it's necessary to promote to int */
4273 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4274 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4276 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4277 if it's possible to use a 'signed char' */
4279 /* is left a 'unsigned char'? */
4280 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4281 /* the value range of a 'unsigned char' is 0...255;
4282 if the actual value is < 128 it can be changed to signed */
4283 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4285 /* now we've got 2 'signed char'! */
4286 SPEC_USIGN (RETYPE (tree)) = 0;
4288 /* same test for the left operand: */
4289 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4290 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4292 SPEC_USIGN (LETYPE (tree)) = 0;
4296 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4297 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4298 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4302 LRVAL (tree) = RRVAL (tree) = 1;
4303 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4305 /* condition transformations */
4307 unsigned transformedOp = 0;
4309 switch (tree->opval.op)
4311 case '<': /* transform (a < b) to !(a >= b) */
4313 transformedOp = GE_OP;
4315 case '>': /* transform (a > b) to !(a <= b) */
4317 transformedOp = LE_OP;
4319 case LE_OP: /* transform (a <= b) to !(a > b) */
4321 transformedOp = '>';
4323 case GE_OP: /* transform (a >= b) to !(a < b) */
4325 transformedOp = '<';
4327 case NE_OP: /* transform (a != b) to !(a == b) */
4329 transformedOp = EQ_OP;
4331 case EQ_OP: /* transform (a == b) to !(a != b) */
4333 transformedOp = NE_OP;
4340 tree->opval.op = transformedOp;
4341 tree->decorated = 0;
4342 tree = newNode ('!', tree, NULL);
4343 tree->filename = tree->left->filename;
4344 tree->lineno = tree->left->lineno;
4345 return decorateType (tree, resultType);
4351 /*------------------------------------------------------------------*/
4352 /*----------------------------*/
4354 /*----------------------------*/
4355 case SIZEOF: /* evaluate wihout code generation */
4356 /* change the type to a integer */
4358 int size = getSize (tree->right->ftype);
4360 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4361 if (!size && !IS_VOID(tree->right->ftype))
4362 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4364 tree->type = EX_VALUE;
4365 tree->opval.val = constVal (buffer);
4366 tree->right = tree->left = NULL;
4367 TETYPE (tree) = getSpec (TTYPE (tree) =
4368 tree->opval.val->type);
4372 /*------------------------------------------------------------------*/
4373 /*----------------------------*/
4375 /*----------------------------*/
4377 /* return typeof enum value */
4378 tree->type = EX_VALUE;
4381 if (IS_SPEC(tree->right->ftype)) {
4382 switch (SPEC_NOUN(tree->right->ftype)) {
4384 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4385 else typeofv = TYPEOF_INT;
4388 typeofv = TYPEOF_FLOAT;
4391 typeofv = TYPEOF_FIXED16X16;
4394 typeofv = TYPEOF_CHAR;
4397 typeofv = TYPEOF_VOID;
4400 typeofv = TYPEOF_STRUCT;
4403 typeofv = TYPEOF_BITFIELD;
4406 typeofv = TYPEOF_BIT;
4409 typeofv = TYPEOF_SBIT;
4415 switch (DCL_TYPE(tree->right->ftype)) {
4417 typeofv = TYPEOF_POINTER;
4420 typeofv = TYPEOF_FPOINTER;
4423 typeofv = TYPEOF_CPOINTER;
4426 typeofv = TYPEOF_GPOINTER;
4429 typeofv = TYPEOF_PPOINTER;
4432 typeofv = TYPEOF_IPOINTER;
4435 typeofv = TYPEOF_ARRAY;
4438 typeofv = TYPEOF_FUNCTION;
4444 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4445 tree->opval.val = constVal (buffer);
4446 tree->right = tree->left = NULL;
4447 TETYPE (tree) = getSpec (TTYPE (tree) =
4448 tree->opval.val->type);
4451 /*------------------------------------------------------------------*/
4452 /*----------------------------*/
4453 /* conditional operator '?' */
4454 /*----------------------------*/
4456 /* the type is value of the colon operator (on the right) */
4457 assert (IS_COLON_OP (tree->right));
4459 /* If already known then replace the tree : optimizer will do it
4460 but faster to do it here. If done before decorating tree->right
4461 this can save generating unused const strings. */
4462 if (IS_LITERAL (LTYPE (tree)))
4464 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4465 return decorateType (tree->right->left, resultTypeProp);
4467 return decorateType (tree->right->right, resultTypeProp);
4470 tree->right = decorateType (tree->right, resultTypeProp);
4472 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4473 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4475 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4476 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4478 if ((valTrue != 0) && (valFalse == 0))
4480 /* assign cond to result */
4481 tree->left->decorated = 0;
4482 return decorateType (tree->left, resultTypeProp);
4484 else if ((valTrue == 0) && (valFalse != 0))
4486 /* assign !cond to result */
4487 tree->opval.op = '!';
4488 tree->decorated = 0;
4490 return decorateType (tree, resultTypeProp);
4494 /* they have the same boolean value, make them equal */
4495 tree->right->left = tree->right->right;
4499 /* if they are equal then replace the tree */
4500 if (isAstEqual (tree->right->left, tree->right->right))
4502 return tree->right->left;
4505 TTYPE (tree) = RTYPE (tree);
4506 TETYPE (tree) = getSpec (TTYPE (tree));
4510 /* if they don't match we have a problem */
4511 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4512 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4514 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4515 goto errorTreeReturn;
4518 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4519 resultType, tree->opval.op);
4520 TETYPE (tree) = getSpec (TTYPE (tree));
4524 #if 0 // assignment operators are converted by the parser
4525 /*------------------------------------------------------------------*/
4526 /*----------------------------*/
4527 /* assignment operators */
4528 /*----------------------------*/
4531 /* for these it must be both must be integral */
4532 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4533 !IS_ARITHMETIC (RTYPE (tree)))
4535 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4536 goto errorTreeReturn;
4539 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4541 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4542 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4546 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4547 goto errorTreeReturn;
4558 /* for these it must be both must be integral */
4559 if (!IS_INTEGRAL (LTYPE (tree)) ||
4560 !IS_INTEGRAL (RTYPE (tree)))
4562 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4563 goto errorTreeReturn;
4566 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4568 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4569 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4573 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4574 goto errorTreeReturn;
4580 /*------------------------------------------------------------------*/
4581 /*----------------------------*/
4583 /*----------------------------*/
4585 if (!(IS_PTR (LTYPE (tree)) ||
4586 IS_ARITHMETIC (LTYPE (tree))))
4588 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4589 goto errorTreeReturn;
4592 if (!(IS_PTR (RTYPE (tree)) ||
4593 IS_ARITHMETIC (RTYPE (tree))))
4595 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4596 goto errorTreeReturn;
4599 TETYPE (tree) = getSpec (TTYPE (tree) =
4600 computeType (LTYPE (tree),
4605 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4606 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4610 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4611 goto errorTreeReturn;
4617 /*------------------------------------------------------------------*/
4618 /*----------------------------*/
4620 /*----------------------------*/
4622 /* this is not a unary operation */
4623 /* if both pointers then problem */
4624 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4626 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4627 goto errorTreeReturn;
4630 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4632 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4633 goto errorTreeReturn;
4636 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4638 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4639 goto errorTreeReturn;
4642 TETYPE (tree) = getSpec (TTYPE (tree) =
4643 computeType (LTYPE (tree),
4648 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4649 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4653 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4654 goto errorTreeReturn;
4657 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4658 tree->opval.op = '=';
4663 /*------------------------------------------------------------------*/
4664 /*----------------------------*/
4665 /* straight assignemnt */
4666 /*----------------------------*/
4668 /* cannot be an aggregate */
4669 if (IS_AGGREGATE (LTYPE (tree)))
4671 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4672 goto errorTreeReturn;
4675 /* they should either match or be castable */
4676 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4678 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4679 printFromToType(RTYPE(tree),LTYPE(tree));
4682 /* if the left side of the tree is of type void
4683 then report error */
4684 if (IS_VOID (LTYPE (tree)))
4686 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4687 printFromToType(RTYPE(tree), LTYPE(tree));
4690 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4693 if (!tree->initMode ) {
4694 if (IS_CONSTANT(LTYPE(tree)))
4695 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4699 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4700 goto errorTreeReturn;
4705 /*------------------------------------------------------------------*/
4706 /*----------------------------*/
4707 /* comma operator */
4708 /*----------------------------*/
4710 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4713 /*------------------------------------------------------------------*/
4714 /*----------------------------*/
4716 /*----------------------------*/
4719 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4720 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4722 if (tree->left->opval.op == '*' && !tree->left->right)
4723 tree->left = tree->left->left;
4726 /* require a function or pointer to function */
4727 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4729 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4730 goto errorTreeReturn;
4733 /* if there are parms, make sure that
4734 parms are decorate / process / reverse only once */
4736 !tree->right->decorated)
4741 if (IS_FUNCPTR (LTYPE (tree)))
4743 functype = LTYPE (tree)->next;
4744 processFuncPtrArgs (functype);
4747 functype = LTYPE (tree);
4749 if (processParms (tree->left, FUNC_ARGS(functype),
4750 &tree->right, &parmNumber, TRUE))
4752 goto errorTreeReturn;
4755 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4756 !IFFUNC_ISBUILTIN(functype))
4758 reverseParms (tree->right);
4761 TTYPE (tree) = functype->next;
4762 TETYPE (tree) = getSpec (TTYPE (tree));
4766 /*------------------------------------------------------------------*/
4767 /*----------------------------*/
4768 /* return statement */
4769 /*----------------------------*/
4774 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4776 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4777 printFromToType (RTYPE(tree), currFunc->type->next);
4778 goto errorTreeReturn;
4781 if (IS_VOID (currFunc->type->next)
4783 !IS_VOID (RTYPE (tree)))
4785 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4786 goto errorTreeReturn;
4789 /* if there is going to be a casting required then add it */
4790 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4793 decorateType (newNode (CAST,
4794 newAst_LINK (copyLinkChain (currFunc->type->next)),
4796 IS_GENPTR (currFunc->type->next) ? RESULT_TYPE_GPTR : RESULT_TYPE_NONE);
4804 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4806 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4807 goto errorTreeReturn;
4810 TTYPE (tree) = TETYPE (tree) = NULL;
4813 /*------------------------------------------------------------------*/
4814 /*----------------------------*/
4815 /* switch statement */
4816 /*----------------------------*/
4818 /* the switch value must be an integer */
4819 if (!IS_INTEGRAL (LTYPE (tree)))
4821 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4822 goto errorTreeReturn;
4825 TTYPE (tree) = TETYPE (tree) = NULL;
4828 /*------------------------------------------------------------------*/
4829 /*----------------------------*/
4831 /*----------------------------*/
4833 tree->left = backPatchLabels (tree->left,
4836 TTYPE (tree) = TETYPE (tree) = NULL;
4839 /*------------------------------------------------------------------*/
4840 /*----------------------------*/
4842 /*----------------------------*/
4845 AST_FOR (tree, initExpr) = decorateType (
4846 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4847 AST_FOR (tree, condExpr) = decorateType (
4848 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4849 AST_FOR (tree, loopExpr) = decorateType (
4850 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4852 /* if the for loop is reversible then
4853 reverse it otherwise do what we normally
4859 if (isLoopReversible (tree, &sym, &init, &end))
4860 return reverseLoop (tree, sym, init, end);
4862 return decorateType (createFor (AST_FOR (tree, trueLabel),
4863 AST_FOR (tree, continueLabel),
4864 AST_FOR (tree, falseLabel),
4865 AST_FOR (tree, condLabel),
4866 AST_FOR (tree, initExpr),
4867 AST_FOR (tree, condExpr),
4868 AST_FOR (tree, loopExpr),
4869 tree->left), RESULT_TYPE_NONE);
4872 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4873 "node PARAM shouldn't be processed here");
4874 /* but in processParams() */
4877 TTYPE (tree) = TETYPE (tree) = NULL;
4881 /* some error found this tree will be killed */
4883 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4884 tree->opval.op = NULLOP;
4890 /*-----------------------------------------------------------------*/
4891 /* sizeofOp - processes size of operation */
4892 /*-----------------------------------------------------------------*/
4894 sizeofOp (sym_link * type)
4899 /* make sure the type is complete and sane */
4900 checkTypeSanity(type, "(sizeof)");
4902 /* get the size and convert it to character */
4903 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4904 if (!size && !IS_VOID(type))
4905 werror (E_SIZEOF_INCOMPLETE_TYPE);
4907 /* now convert into value */
4908 return constVal (buff);
4912 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4913 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4914 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4915 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4916 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4917 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4918 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4920 /*-----------------------------------------------------------------*/
4921 /* backPatchLabels - change and or not operators to flow control */
4922 /*-----------------------------------------------------------------*/
4924 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4930 /* while-loops insert a label between the IFX and the condition,
4931 therefore look behind the label too */
4932 if (tree->opval.op == LABEL &&
4934 IS_ANDORNOT (tree->right))
4936 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4940 if (!(IS_ANDORNOT (tree)))
4943 /* if this an and */
4946 static int localLbl = 0;
4949 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4950 localLabel = newSymbol (buffer, NestLevel);
4952 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4954 /* if left is already a IFX then just change the if true label in that */
4955 if (!IS_IFX (tree->left))
4956 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4958 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4959 /* right is a IFX then just join */
4960 if (IS_IFX (tree->right))
4961 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4963 tree->right = createLabel (localLabel, tree->right);
4964 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4966 return newNode (NULLOP, tree->left, tree->right);
4969 /* if this is an or operation */
4972 static int localLbl = 0;
4975 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4976 localLabel = newSymbol (buffer, NestLevel);
4978 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4980 /* if left is already a IFX then just change the if true label in that */
4981 if (!IS_IFX (tree->left))
4982 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4984 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4985 /* right is a IFX then just join */
4986 if (IS_IFX (tree->right))
4987 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4989 tree->right = createLabel (localLabel, tree->right);
4990 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4992 return newNode (NULLOP, tree->left, tree->right);
4998 /* call with exchanged labels */
4999 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
5001 /* if left isn't already a IFX */
5002 if (!IS_IFX (tree->left))
5004 tree->left = newNode (IFX, tree->left, NULL);
5005 tree->left->trueLabel = falseLabel;
5006 tree->left->falseLabel = trueLabel;
5013 tree->trueLabel = trueLabel;
5014 tree->falseLabel = falseLabel;
5021 /*-----------------------------------------------------------------*/
5022 /* createBlock - create expression tree for block */
5023 /*-----------------------------------------------------------------*/
5025 createBlock (symbol * decl, ast * body)
5029 /* if the block has nothing */
5033 ex = newNode (BLOCK, NULL, body);
5034 ex->values.sym = decl;
5037 ex->filename = NULL;
5042 /*-----------------------------------------------------------------*/
5043 /* createLabel - creates the expression tree for labels */
5044 /*-----------------------------------------------------------------*/
5046 createLabel (symbol * label, ast * stmnt)
5049 char name[SDCC_NAME_MAX + 1];
5052 /* must create fresh symbol if the symbol name */
5053 /* exists in the symbol table, since there can */
5054 /* be a variable with the same name as the labl */
5055 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
5056 (csym->level == label->level))
5057 label = newSymbol (label->name, label->level);
5059 /* change the name before putting it in add _ */
5060 SNPRINTF(name, sizeof(name), "%s", label->name);
5062 /* put the label in the LabelSymbol table */
5063 /* but first check if a label of the same */
5065 if ((csym = findSym (LabelTab, NULL, name)))
5066 werror (E_DUPLICATE_LABEL, label->name);
5068 addSym (LabelTab, label, name, label->level, 0, 0);
5072 label->key = labelKey++;
5073 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
5074 rValue->filename = NULL;
5080 /*-----------------------------------------------------------------*/
5081 /* createCase - generates the parsetree for a case statement */
5082 /*-----------------------------------------------------------------*/
5084 createCase (ast * swStat, ast * caseVal, ast * stmnt)
5086 char caseLbl[SDCC_NAME_MAX + 1];
5090 /* if the switch statement does not exist */
5091 /* then case is out of context */
5094 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5098 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5099 /* if not a constant then error */
5100 if (!IS_LITERAL (caseVal->ftype))
5102 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5106 /* if not a integer than error */
5107 if (!IS_INTEGRAL (caseVal->ftype))
5109 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5113 /* find the end of the switch values chain */
5114 if (!(val = swStat->values.switchVals.swVals))
5115 swStat->values.switchVals.swVals = caseVal->opval.val;
5118 /* also order the cases according to value */
5120 int cVal = (int) ulFromVal (caseVal->opval.val);
5121 while (val && (int) ulFromVal (val) < cVal)
5127 /* if we reached the end then */
5130 pval->next = caseVal->opval.val;
5132 else if ((int) ulFromVal (val) == cVal)
5134 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5140 /* we found a value greater than */
5141 /* the current value we must add this */
5142 /* before the value */
5143 caseVal->opval.val->next = val;
5145 /* if this was the first in chain */
5146 if (swStat->values.switchVals.swVals == val)
5147 swStat->values.switchVals.swVals =
5150 pval->next = caseVal->opval.val;
5155 /* create the case label */
5156 SNPRINTF(caseLbl, sizeof(caseLbl),
5158 swStat->values.switchVals.swNum,
5159 (int) ulFromVal (caseVal->opval.val));
5161 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5162 rexpr->filename = 0;
5167 /*-----------------------------------------------------------------*/
5168 /* createDefault - creates the parse tree for the default statement */
5169 /*-----------------------------------------------------------------*/
5171 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5173 char defLbl[SDCC_NAME_MAX + 1];
5175 /* if the switch statement does not exist */
5176 /* then case is out of context */
5179 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5183 if (swStat->values.switchVals.swDefault)
5185 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5190 /* turn on the default flag */
5191 swStat->values.switchVals.swDefault = 1;
5193 /* create the label */
5194 SNPRINTF (defLbl, sizeof(defLbl),
5195 "_default_%d", swStat->values.switchVals.swNum);
5196 return createLabel (newSymbol (defLbl, 0), stmnt);
5199 /*-----------------------------------------------------------------*/
5200 /* createIf - creates the parsetree for the if statement */
5201 /*-----------------------------------------------------------------*/
5203 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5205 static int Lblnum = 0;
5207 symbol *ifTrue, *ifFalse, *ifEnd;
5209 /* if neither exists */
5210 if (!elseBody && !ifBody) {
5211 // if there are no side effects (i++, j() etc)
5212 if (!hasSEFcalls(condAst)) {
5217 /* create the labels */
5218 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5219 ifFalse = newSymbol (buffer, NestLevel);
5220 /* if no else body then end == false */
5225 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5226 ifEnd = newSymbol (buffer, NestLevel);
5229 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5230 ifTrue = newSymbol (buffer, NestLevel);
5234 /* attach the ifTrue label to the top of it body */
5235 ifBody = createLabel (ifTrue, ifBody);
5236 /* attach a goto end to the ifBody if else is present */
5239 ifBody = newNode (NULLOP, ifBody,
5241 newAst_VALUE (symbolVal (ifEnd)),
5243 /* put the elseLabel on the else body */
5244 elseBody = createLabel (ifFalse, elseBody);
5245 /* out the end at the end of the body */
5246 elseBody = newNode (NULLOP,
5248 createLabel (ifEnd, NULL));
5252 ifBody = newNode (NULLOP, ifBody,
5253 createLabel (ifFalse, NULL));
5255 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5256 if (IS_IFX (condAst))
5259 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5261 return newNode (NULLOP, ifTree,
5262 newNode (NULLOP, ifBody, elseBody));
5266 /*-----------------------------------------------------------------*/
5267 /* createDo - creates parse tree for do */
5270 /* _docontinue_n: */
5271 /* condition_expression +-> trueLabel -> _dobody_n */
5273 /* +-> falseLabel-> _dobreak_n */
5275 /*-----------------------------------------------------------------*/
5277 createDo (symbol * trueLabel, symbol * continueLabel,
5278 symbol * falseLabel, ast * condAst, ast * doBody)
5283 /* if the body does not exist then it is simple */
5286 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5287 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5288 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5289 doTree->trueLabel = continueLabel;
5290 doTree->falseLabel = NULL;
5292 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5296 /* otherwise we have a body */
5297 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5299 /* attach the body label to the top */
5300 doBody = createLabel (trueLabel, doBody);
5301 /* attach the continue label to end of body */
5302 doBody = newNode (NULLOP, doBody,
5303 createLabel (continueLabel, NULL));
5305 /* now put the break label at the end */
5306 if (IS_IFX (condAst))
5309 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5311 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5313 /* putting it together */
5314 return newNode (NULLOP, doBody, doTree);
5317 /*-----------------------------------------------------------------*/
5318 /* createFor - creates parse tree for 'for' statement */
5321 /* condExpr +-> trueLabel -> _forbody_n */
5323 /* +-> falseLabel-> _forbreak_n */
5326 /* _forcontinue_n: */
5328 /* goto _forcond_n ; */
5330 /*-----------------------------------------------------------------*/
5332 createFor (symbol * trueLabel, symbol * continueLabel,
5333 symbol * falseLabel, symbol * condLabel,
5334 ast * initExpr, ast * condExpr, ast * loopExpr,
5339 /* if loopexpression not present then we can generate it */
5340 /* the same way as a while */
5342 return newNode (NULLOP, initExpr,
5343 createWhile (trueLabel, continueLabel,
5344 falseLabel, condExpr, forBody));
5345 /* vanilla for statement */
5346 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5348 if (condExpr && !IS_IFX (condExpr))
5349 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5352 /* attach condition label to condition */
5353 condExpr = createLabel (condLabel, condExpr);
5355 /* attach body label to body */
5356 forBody = createLabel (trueLabel, forBody);
5358 /* attach continue to forLoop expression & attach */
5359 /* goto the forcond @ and of loopExpression */
5360 loopExpr = createLabel (continueLabel,
5364 newAst_VALUE (symbolVal (condLabel)),
5366 /* now start putting them together */
5367 forTree = newNode (NULLOP, initExpr, condExpr);
5368 forTree = newNode (NULLOP, forTree, forBody);
5369 forTree = newNode (NULLOP, forTree, loopExpr);
5370 /* finally add the break label */
5371 forTree = newNode (NULLOP, forTree,
5372 createLabel (falseLabel, NULL));
5376 /*-----------------------------------------------------------------*/
5377 /* createWhile - creates parse tree for while statement */
5378 /* the while statement will be created as follows */
5380 /* _while_continue_n: */
5381 /* condition_expression +-> trueLabel -> _while_boby_n */
5383 /* +-> falseLabel -> _while_break_n */
5384 /* _while_body_n: */
5386 /* goto _while_continue_n */
5387 /* _while_break_n: */
5388 /*-----------------------------------------------------------------*/
5390 createWhile (symbol * trueLabel, symbol * continueLabel,
5391 symbol * falseLabel, ast * condExpr, ast * whileBody)
5395 /* put the continue label */
5396 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5397 condExpr = createLabel (continueLabel, condExpr);
5398 condExpr->filename = NULL;
5399 condExpr->lineno = 0;
5401 /* put the body label in front of the body */
5402 whileBody = createLabel (trueLabel, whileBody);
5403 whileBody->filename = NULL;
5404 whileBody->lineno = 0;
5405 /* put a jump to continue at the end of the body */
5406 /* and put break label at the end of the body */
5407 whileBody = newNode (NULLOP,
5410 newAst_VALUE (symbolVal (continueLabel)),
5411 createLabel (falseLabel, NULL)));
5413 /* put it all together */
5414 if (IS_IFX (condExpr))
5415 whileTree = condExpr;
5418 whileTree = newNode (IFX, condExpr, NULL);
5419 /* put the true & false labels in place */
5420 whileTree->trueLabel = trueLabel;
5421 whileTree->falseLabel = falseLabel;
5424 return newNode (NULLOP, whileTree, whileBody);
5427 /*-----------------------------------------------------------------*/
5428 /* isShiftRightLitVal _BitAndLitVal - helper function */
5429 /*-----------------------------------------------------------------*/
5431 isShiftRightLitVal_BitAndLitVal (ast * tree)
5433 /* if this is not a bit and */
5434 if (!IS_BITAND (tree))
5437 /* will look for tree of the form
5438 ( expr >> litval2) & litval1 */
5439 if (!IS_AST_LIT_VALUE (tree->right))
5442 if (!IS_RIGHT_OP (tree->left))
5445 if (!IS_AST_LIT_VALUE (tree->left->right))
5448 return tree->left->left;
5451 /*-----------------------------------------------------------------*/
5452 /* isBitAndPowOf2 - helper function */
5453 /*-----------------------------------------------------------------*/
5455 isBitAndPow2 (ast * tree)
5457 /* if this is not a bit and */
5458 if (!IS_BITAND (tree))
5461 /* will look for tree of the form
5462 ( expr & (1 << litval) */
5463 if (!IS_AST_LIT_VALUE (tree->right))
5466 return powof2 (AST_ULONG_VALUE (tree->right));
5469 /*-----------------------------------------------------------------*/
5470 /* optimizeGetHbit - get highest order bit of the expression */
5471 /*-----------------------------------------------------------------*/
5473 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5478 expr = isShiftRightLitVal_BitAndLitVal(tree);
5481 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5482 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5483 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5486 if (!expr && (resultType == RESULT_TYPE_BIT))
5489 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5495 /* make sure the port supports GETHBIT */
5496 if (port->hasExtBitOp
5497 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5500 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5503 /*-----------------------------------------------------------------*/
5504 /* optimizeGetAbit - get a single bit of the expression */
5505 /*-----------------------------------------------------------------*/
5507 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5512 expr = isShiftRightLitVal_BitAndLitVal(tree);
5515 if (AST_ULONG_VALUE (tree->right) != 1)
5517 count = tree->left->right;
5519 if (!expr && (resultType == RESULT_TYPE_BIT))
5521 int p2 = isBitAndPow2 (tree);
5525 count = newAst_VALUE (valueFromLit (p2));
5531 /* make sure the port supports GETABIT */
5532 if (port->hasExtBitOp
5533 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5536 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5540 /*-----------------------------------------------------------------*/
5541 /* optimizeGetByte - get a byte of the expression */
5542 /*-----------------------------------------------------------------*/
5544 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5550 expr = isShiftRightLitVal_BitAndLitVal(tree);
5553 i = AST_ULONG_VALUE (tree->left->right);
5554 count = tree->left->right;
5555 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5558 if (!expr && resultType == RESULT_TYPE_CHAR)
5560 /* if this is a right shift over a multiple of 8 */
5561 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5563 i = AST_ULONG_VALUE (tree->right);
5564 count = tree->right;
5568 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5571 /* make sure the port supports GETBYTE */
5572 if (port->hasExtBitOp
5573 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5576 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5579 /*-----------------------------------------------------------------*/
5580 /* optimizeGetWord - get two bytes of the expression */
5581 /*-----------------------------------------------------------------*/
5583 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5589 expr = isShiftRightLitVal_BitAndLitVal(tree);
5592 i = AST_ULONG_VALUE (tree->left->right);
5593 count = tree->left->right;
5594 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5597 if (!expr && resultType == RESULT_TYPE_INT)
5599 /* if this is a right shift over a multiple of 8 */
5600 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5602 i = AST_ULONG_VALUE (tree->right);
5603 count = tree->right;
5607 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5610 /* make sure the port supports GETWORD */
5611 if (port->hasExtBitOp
5612 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5615 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5618 /*-----------------------------------------------------------------*/
5619 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5620 /*-----------------------------------------------------------------*/
5622 optimizeRRCRLC (ast * root)
5624 /* will look for trees of the form
5625 (?expr << 1) | (?expr >> 7) or
5626 (?expr >> 7) | (?expr << 1) will make that
5627 into a RLC : operation ..
5629 (?expr >> 1) | (?expr << 7) or
5630 (?expr << 7) | (?expr >> 1) will make that
5631 into a RRC operation
5632 note : by 7 I mean (number of bits required to hold the
5634 /* if the root operation is not a | operation then not */
5635 if (!IS_BITOR (root))
5638 /* I have to think of a better way to match patterns this sucks */
5639 /* that aside let's start looking for the first case : I use a
5640 negative check a lot to improve the efficiency */
5641 /* (?expr << 1) | (?expr >> 7) */
5642 if (IS_LEFT_OP (root->left) &&
5643 IS_RIGHT_OP (root->right))
5646 if (!SPEC_USIGN (TETYPE (root->left->left)))
5649 if (!IS_AST_LIT_VALUE (root->left->right) ||
5650 !IS_AST_LIT_VALUE (root->right->right))
5653 /* make sure it is the same expression */
5654 if (!isAstEqual (root->left->left,
5658 if (AST_ULONG_VALUE (root->left->right) != 1)
5661 if (AST_ULONG_VALUE (root->right->right) !=
5662 (getSize (TTYPE (root->left->left)) * 8 - 1))
5665 /* make sure the port supports RLC */
5666 if (port->hasExtBitOp
5667 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5670 /* whew got the first case : create the AST */
5671 return newNode (RLC, root->left->left, NULL);
5675 /* check for second case */
5676 /* (?expr >> 7) | (?expr << 1) */
5677 if (IS_LEFT_OP (root->right) &&
5678 IS_RIGHT_OP (root->left))
5681 if (!SPEC_USIGN (TETYPE (root->left->left)))
5684 if (!IS_AST_LIT_VALUE (root->left->right) ||
5685 !IS_AST_LIT_VALUE (root->right->right))
5688 /* make sure it is the same symbol */
5689 if (!isAstEqual (root->left->left,
5693 if (AST_ULONG_VALUE (root->right->right) != 1)
5696 if (AST_ULONG_VALUE (root->left->right) !=
5697 (getSize (TTYPE (root->left->left)) * 8 - 1))
5700 /* make sure the port supports RLC */
5701 if (port->hasExtBitOp
5702 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5705 /* whew got the first case : create the AST */
5706 return newNode (RLC, root->left->left, NULL);
5711 /* third case for RRC */
5712 /* (?symbol >> 1) | (?symbol << 7) */
5713 if (IS_LEFT_OP (root->right) &&
5714 IS_RIGHT_OP (root->left))
5717 if (!SPEC_USIGN (TETYPE (root->left->left)))
5720 if (!IS_AST_LIT_VALUE (root->left->right) ||
5721 !IS_AST_LIT_VALUE (root->right->right))
5724 /* make sure it is the same symbol */
5725 if (!isAstEqual (root->left->left,
5729 if (AST_ULONG_VALUE (root->left->right) != 1)
5732 if (AST_ULONG_VALUE (root->right->right) !=
5733 (getSize (TTYPE (root->left->left)) * 8 - 1))
5736 /* make sure the port supports RRC */
5737 if (port->hasExtBitOp
5738 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5741 /* whew got the first case : create the AST */
5742 return newNode (RRC, root->left->left, NULL);
5746 /* fourth and last case for now */
5747 /* (?symbol << 7) | (?symbol >> 1) */
5748 if (IS_RIGHT_OP (root->right) &&
5749 IS_LEFT_OP (root->left))
5752 if (!SPEC_USIGN (TETYPE (root->left->left)))
5755 if (!IS_AST_LIT_VALUE (root->left->right) ||
5756 !IS_AST_LIT_VALUE (root->right->right))
5759 /* make sure it is the same symbol */
5760 if (!isAstEqual (root->left->left,
5764 if (AST_ULONG_VALUE (root->right->right) != 1)
5767 if (AST_ULONG_VALUE (root->left->right) !=
5768 (getSize (TTYPE (root->left->left)) * 8 - 1))
5771 /* make sure the port supports RRC */
5772 if (port->hasExtBitOp
5773 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5776 /* whew got the first case : create the AST */
5777 return newNode (RRC, root->left->left, NULL);
5781 /* not found return root */
5785 /*-----------------------------------------------------------------*/
5786 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5787 /*-----------------------------------------------------------------*/
5789 optimizeSWAP (ast * root)
5791 /* will look for trees of the form
5792 (?expr << 4) | (?expr >> 4) or
5793 (?expr >> 4) | (?expr << 4) will make that
5794 into a SWAP : operation ..
5795 note : by 4 I mean (number of bits required to hold the
5797 /* if the root operation is not a | operation then not */
5798 if (!IS_BITOR (root))
5801 /* (?expr << 4) | (?expr >> 4) */
5802 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5803 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5806 if (!SPEC_USIGN (TETYPE (root->left->left)))
5809 if (!IS_AST_LIT_VALUE (root->left->right) ||
5810 !IS_AST_LIT_VALUE (root->right->right))
5813 /* make sure it is the same expression */
5814 if (!isAstEqual (root->left->left,
5818 if (AST_ULONG_VALUE (root->left->right) !=
5819 (getSize (TTYPE (root->left->left)) * 4))
5822 if (AST_ULONG_VALUE (root->right->right) !=
5823 (getSize (TTYPE (root->left->left)) * 4))
5826 /* make sure the port supports SWAP */
5827 if (port->hasExtBitOp
5828 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5831 /* found it : create the AST */
5832 return newNode (SWAP, root->left->left, NULL);
5836 /* not found return root */
5840 /*-----------------------------------------------------------------*/
5841 /* optimizeCompare - optimizes compares for bit variables */
5842 /*-----------------------------------------------------------------*/
5844 optimizeCompare (ast * root)
5846 ast *optExpr = NULL;
5849 unsigned int litValue;
5851 /* if nothing then return nothing */
5855 /* if not a compare op then do leaves */
5856 if (!IS_COMPARE_OP (root))
5858 root->left = optimizeCompare (root->left);
5859 root->right = optimizeCompare (root->right);
5863 /* if left & right are the same then depending
5864 of the operation do */
5865 if (isAstEqual (root->left, root->right))
5867 switch (root->opval.op)
5872 optExpr = newAst_VALUE (constCharVal (0));
5877 optExpr = newAst_VALUE (constCharVal (1));
5881 return decorateType (optExpr, RESULT_TYPE_NONE);
5884 vleft = (root->left->type == EX_VALUE ?
5885 root->left->opval.val : NULL);
5887 vright = (root->right->type == EX_VALUE ?
5888 root->right->opval.val : NULL);
5890 /* if left is a BITVAR in BITSPACE */
5891 /* and right is a LITERAL then */
5892 /* optimize else do nothing */
5893 if (vleft && vright &&
5894 IS_BITVAR (vleft->etype) &&
5895 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5896 IS_LITERAL (vright->etype))
5899 /* if right side > 1 then comparison may never succeed */
5900 if ((litValue = (int) ulFromVal (vright)) > 1)
5902 werror (W_BAD_COMPARE);
5908 switch (root->opval.op)
5910 case '>': /* bit value greater than 1 cannot be */
5911 werror (W_BAD_COMPARE);
5915 case '<': /* bit value < 1 means 0 */
5917 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5920 case LE_OP: /* bit value <= 1 means no check */
5921 optExpr = newAst_VALUE (vright);
5924 case GE_OP: /* bit value >= 1 means only check for = */
5926 optExpr = newAst_VALUE (vleft);
5931 { /* literal is zero */
5932 switch (root->opval.op)
5934 case '<': /* bit value < 0 cannot be */
5935 werror (W_BAD_COMPARE);
5939 case '>': /* bit value > 0 means 1 */
5941 optExpr = newAst_VALUE (vleft);
5944 case LE_OP: /* bit value <= 0 means no check */
5945 case GE_OP: /* bit value >= 0 means no check */
5946 werror (W_BAD_COMPARE);
5950 case EQ_OP: /* bit == 0 means ! of bit */
5951 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5955 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5956 } /* end-of-if of BITVAR */
5962 /*-----------------------------------------------------------------*/
5963 /* addSymToBlock : adds the symbol to the first block we find */
5964 /*-----------------------------------------------------------------*/
5966 addSymToBlock (symbol * sym, ast * tree)
5968 /* reached end of tree or a leaf */
5969 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5973 if (IS_AST_OP (tree) &&
5974 tree->opval.op == BLOCK)
5977 symbol *lsym = copySymbol (sym);
5979 lsym->next = AST_VALUES (tree, sym);
5980 AST_VALUES (tree, sym) = lsym;
5984 addSymToBlock (sym, tree->left);
5985 addSymToBlock (sym, tree->right);
5988 /*-----------------------------------------------------------------*/
5989 /* processRegParms - do processing for register parameters */
5990 /*-----------------------------------------------------------------*/
5992 processRegParms (value * args, ast * body)
5996 if (IS_REGPARM (args->etype))
5997 addSymToBlock (args->sym, body);
6002 /*-----------------------------------------------------------------*/
6003 /* resetParmKey - resets the operandkeys for the symbols */
6004 /*-----------------------------------------------------------------*/
6005 DEFSETFUNC (resetParmKey)
6016 /*------------------------------------------------------------------*/
6017 /* fixupInlineLabel - change a label in an inlined function so that */
6018 /* it is always unique no matter how many times */
6019 /* the function is inlined. */
6020 /*------------------------------------------------------------------*/
6022 fixupInlineLabel (symbol * sym)
6024 char name[SDCC_NAME_MAX + 1];
6026 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
6027 strcpy (sym->name, name);
6030 /*------------------------------------------------------------------*/
6031 /* copyAstLoc - copy location information (file, line, block, etc.) */
6032 /* from one ast node to another */
6033 /*------------------------------------------------------------------*/
6035 copyAstLoc (ast * dest, ast * src)
6037 dest->filename = src->filename;
6038 dest->lineno = src->lineno;
6039 dest->level = src->level;
6040 dest->block = src->block;
6041 dest->seqPoint = src->seqPoint;
6044 /*-----------------------------------------------------------------*/
6045 /* fixupInline - perform various fixups on an inline function tree */
6046 /* to take into account that it is no longer a */
6047 /* stand-alone function. */
6048 /*-----------------------------------------------------------------*/
6050 fixupInline (ast * tree, int level)
6052 int savedBlockno = currBlockno;
6054 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6058 currBlockno = ++blockNo;
6061 /* Add any declared variables back into the symbol table */
6062 decls = tree->values.sym;
6065 decls->level = level;
6066 decls->block = currBlockno;
6067 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
6068 decls = decls->next;
6072 tree->level = level;
6073 tree->block = currBlockno;
6075 /* Update symbols */
6076 if (IS_AST_VALUE (tree) &&
6077 tree->opval.val->sym)
6079 symbol * sym = tree->opval.val->sym;
6082 sym->block = currBlockno;
6085 SYM_SPIL_LOC (sym) = NULL;
6088 /* If the symbol is a label, we need to renumber it */
6090 fixupInlineLabel (sym);
6093 /* Update IFX target labels */
6094 if (tree->type == EX_OP && tree->opval.op == IFX)
6096 if (tree->trueLabel)
6097 fixupInlineLabel (tree->trueLabel);
6098 if (tree->falseLabel)
6099 fixupInlineLabel (tree->falseLabel);
6102 /* Replace RETURN with optional assignment and a GOTO to the end */
6103 /* of the inlined function */
6104 if (tree->type == EX_OP && tree->opval.op == RETURN)
6106 ast * assignTree = NULL;
6109 if (inlineState.retsym && tree->right)
6111 assignTree = newNode ('=',
6112 newAst_VALUE (symbolVal (inlineState.retsym)),
6114 copyAstLoc (assignTree, tree);
6117 gotoTree = newNode (GOTO,
6118 newAst_VALUE (symbolVal (inlineState.retlab)),
6120 copyAstLoc (gotoTree, tree);
6122 tree->opval.op = NULLOP;
6123 tree->left = assignTree;
6124 tree->right = gotoTree;
6127 /* Update any children */
6129 fixupInline (tree->left, level);
6131 fixupInline (tree->right, level);
6133 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6135 symbol * label = tree->left->opval.val->sym;
6137 label->key = labelKey++;
6138 /* Add this label back into the symbol table */
6139 addSym (LabelTab, label, label->name, label->level, 0, 0);
6142 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6145 currBlockno = savedBlockno;
6149 /*-----------------------------------------------------------------*/
6150 /* inlineAddDecl - add a variable declaration to an ast block. It */
6151 /* is also added to the symbol table if addSymTab */
6153 /*-----------------------------------------------------------------*/
6155 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6158 SYM_SPIL_LOC (sym) = NULL;
6162 symbol **decl = &(block->values.sym);
6164 sym->level = block->level;
6165 sym->block = block->block;
6169 if (strcmp ((*decl)->name, sym->name) == 0)
6171 decl = &( (*decl)->next );
6177 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6182 /*-----------------------------------------------------------------*/
6183 /* inlineTempVar - create a temporary variable for inlining */
6184 /*-----------------------------------------------------------------*/
6186 inlineTempVar (sym_link * type, int level)
6190 sym = newSymbol (genSymName(level), level );
6191 sym->type = copyLinkChain (type);
6192 sym->etype = getSpec(sym->type);
6193 SPEC_SCLS (sym->etype) = S_AUTO;
6194 SPEC_OCLS (sym->etype) = NULL;
6195 SPEC_EXTR (sym->etype) = 0;
6196 SPEC_STAT (sym->etype) = 0;
6197 if IS_SPEC (sym->type)
6198 SPEC_VOLATILE (sym->type) = 0;
6200 DCL_PTR_VOLATILE (sym->type) = 0;
6201 SPEC_ABSA (sym->etype) = 0;
6206 /*-----------------------------------------------------------------*/
6207 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6208 /*-----------------------------------------------------------------*/
6210 inlineFindParmRecurse (ast * parms, int *index)
6215 if (parms->type == EX_OP && parms->opval.op == PARAM)
6219 p=inlineFindParmRecurse (parms->left, index);
6222 p=inlineFindParmRecurse (parms->right, index);
6232 /*-----------------------------------------------------------------*/
6233 /* inlineFindParm - search an ast tree of parameters to find one */
6234 /* at a particular index (0=first parameter). */
6235 /* Returns NULL if not found. */
6236 /*-----------------------------------------------------------------*/
6238 inlineFindParm (ast * parms, int index)
6240 return inlineFindParmRecurse (parms, &index);
6243 /*-----------------------------------------------------------------*/
6244 /* expandInlineFuncs - replace calls to inline functions with the */
6245 /* function itself */
6246 /*-----------------------------------------------------------------*/
6248 expandInlineFuncs (ast * tree, ast * block)
6250 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6251 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6253 symbol * func = tree->left->opval.val->sym;
6256 /* The symbol is probably not bound yet, so find the real one */
6257 csym = findSymWithLevel (SymbolTab, func);
6261 /* Is this an inline function that we can inline? */
6262 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6264 symbol * retsym = NULL;
6272 /* Generate a label for the inlined function to branch to */
6273 /* in case it contains a return statement */
6274 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6277 inlineState.retlab = retlab;
6279 /* Build the subtree for the inlined function in the form: */
6280 /* { //inlinetree block */
6281 /* { //inlinetree2 block */
6282 /* inline_function_code; */
6286 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6287 copyAstLoc (temptree, tree);
6288 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6289 copyAstLoc (temptree, tree);
6290 temptree = newNode (BLOCK, NULL, temptree);
6291 copyAstLoc (temptree, tree);
6292 inlinetree2 = temptree;
6293 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6294 copyAstLoc (inlinetree, tree);
6296 /* To pass parameters to the inlined function, we need some */
6297 /* intermediate variables. This avoids scoping problems */
6298 /* when the parameter declaration names are used differently */
6299 /* during the function call. For example, a function */
6300 /* declared as func(int x, int y) but called as func(y,x). */
6301 /* { //inlinetree block */
6302 /* type1 temparg1 = argument1; */
6304 /* typen tempargn = argumentn; */
6305 /* { //inlinetree2 block */
6306 /* type1 param1 = temparg1; */
6308 /* typen paramn = tempargn; */
6309 /* inline_function_code; */
6313 args = FUNC_ARGS (func->type);
6320 ast * passedarg = inlineFindParm (tree->right, argIndex);
6324 werror(E_TOO_FEW_PARMS);
6328 temparg = inlineTempVar (args->sym->type, tree->level+1);
6329 inlineAddDecl (temparg, inlinetree, FALSE);
6331 assigntree = newNode ('=',
6332 newAst_VALUE (symbolVal (temparg)),
6334 assigntree->initMode=1; // tell that assignment is initializer
6335 inlinetree->right = newNode (NULLOP,
6339 parm = copySymbol (args->sym);
6340 inlineAddDecl (parm, inlinetree2, FALSE);
6343 assigntree = newNode ('=',
6344 newAst_VALUE (symbolVal (parm)),
6345 newAst_VALUE (symbolVal (temparg)));
6346 assigntree->initMode=1; // tell that assignment is initializer
6347 inlinetree2->right = newNode (NULLOP,
6349 inlinetree2->right);
6355 /* Handle the return type */
6356 if (!IS_VOID (func->type->next))
6358 /* Create a temporary symbol to hold the return value and */
6359 /* join it with the inlined function using the comma */
6360 /* operator. The fixupInline function will take care of */
6361 /* changing return statements into assignments to retsym. */
6362 /* (parameter passing and return label omitted for clarity) */
6363 /* rettype retsym; */
6365 /* {{inline_function_code}}, retsym */
6367 retsym = inlineTempVar (func->type->next, tree->level);
6368 inlineAddDecl (retsym, block, TRUE);
6370 tree->opval.op = ',';
6371 tree->left = inlinetree;
6372 tree->right = newAst_VALUE (symbolVal (retsym));
6376 tree->opval.op = NULLOP;
6378 tree->right = inlinetree;
6380 inlineState.retsym = retsym;
6382 /* Renumber the various internal counters on the inlined */
6383 /* function's tree nodes and symbols. Add the inlined */
6384 /* function's local variables to the appropriate scope(s). */
6385 /* Convert inlined return statements to an assignment to */
6386 /* retsym (if needed) and a goto retlab. */
6387 fixupInline (inlinetree, inlinetree->level);
6388 inlineState.count++;
6392 /* Recursively continue to search for functions to inline. */
6393 if (IS_AST_OP (tree))
6395 if (tree->opval.op == BLOCK)
6399 expandInlineFuncs (tree->left, block);
6401 expandInlineFuncs (tree->right, block);
6405 /*-----------------------------------------------------------------*/
6406 /* createFunction - This is the key node that calls the iCode for */
6407 /* generating the code for a function. Note code */
6408 /* is generated function by function, later when */
6409 /* add inter-procedural analysis this will change */
6410 /*-----------------------------------------------------------------*/
6412 createFunction (symbol * name, ast * body)
6418 iCode *piCode = NULL;
6420 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6421 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6423 /* if check function return 0 then some problem */
6424 if (checkFunction (name, NULL) == 0)
6427 /* create a dummy block if none exists */
6429 body = newNode (BLOCK, NULL, NULL);
6433 /* check if the function name already in the symbol table */
6434 if ((csym = findSym (SymbolTab, NULL, name->name)))
6437 /* special case for compiler defined functions
6438 we need to add the name to the publics list : this
6439 actually means we are now compiling the compiler
6443 addSet (&publics, name);
6448 addSymChain (&name);
6449 allocVariables (name);
6451 name->lastLine = lexLineno;
6454 /* set the stack pointer */
6455 stackPtr = -port->stack.direction * port->stack.call_overhead;
6458 if (IFFUNC_ISISR (name->type))
6459 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6461 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6463 if (options.useXstack)
6464 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6466 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6469 fetype = getSpec (name->type); /* get the specifier for the function */
6470 /* if this is a reentrant function then */
6471 if (IFFUNC_ISREENT (name->type))
6474 inlineState.count = 0;
6475 expandInlineFuncs (body, NULL);
6477 if (FUNC_ISINLINE (name->type))
6478 name->funcTree = copyAst (body);
6480 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6482 /* do processing for parameters that are passed in registers */
6483 processRegParms (FUNC_ARGS(name->type), body);
6485 /* set the stack pointer */
6489 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6491 /* allocate & autoinit the block variables */
6492 processBlockVars (body, &stack, ALLOCATE);
6494 /* name needs to be mangled */
6495 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6497 body = resolveSymbols (body); /* resolve the symbols */
6498 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6500 /* save the stack information */
6501 if (options.useXstack)
6502 name->xstack = SPEC_STAK (fetype) = stack;
6504 name->stack = SPEC_STAK (fetype) = stack;
6506 ex = newAst_VALUE (symbolVal (name)); /* create name */
6507 ex = newNode (FUNCTION, ex, body);
6508 ex->values.args = FUNC_ARGS(name->type);
6510 if (options.dump_tree)
6515 /* Do not generate code for inline functions unless extern also. */
6517 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6520 /* Temporary hack: always generate code for static inline functions. */
6521 /* Ideally static inline functions should only be generated if needed. */
6522 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6526 /* create the node & generate intermediate code */
6528 codeOutBuf = &code->oBuf;
6529 piCode = iCodeFromAst (ex);
6530 name->generated = 1;
6535 eBBlockFromiCode (piCode);
6537 /* if there are any statics then do them */
6540 GcurMemmap = statsg;
6541 codeOutBuf = &statsg->oBuf;
6542 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6548 /* dealloc the block variables */
6549 processBlockVars (body, &stack, DEALLOCATE);
6550 outputDebugStackSymbols();
6551 /* deallocate paramaters */
6552 deallocParms (FUNC_ARGS(name->type));
6554 if (IFFUNC_ISREENT (name->type))
6557 /* we are done freeup memory & cleanup */
6559 if (port->reset_labelKey)
6562 FUNC_HASBODY(name->type) = 1;
6563 addSet (&operKeyReset, name);
6564 applyToSet (operKeyReset, resetParmKey);
6569 cleanUpLevel (LabelTab, 0);
6570 cleanUpBlock (StructTab, 1);
6571 cleanUpBlock (TypedefTab, 1);
6573 xstack->syms = NULL;
6574 istack->syms = NULL;
6579 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6580 /*-----------------------------------------------------------------*/
6581 /* ast_print : prints the ast (for debugging purposes) */
6582 /*-----------------------------------------------------------------*/
6584 void ast_print (ast * tree, FILE *outfile, int indent)
6589 /* can print only decorated trees */
6590 if (!tree->decorated) return;
6592 /* if any child is an error | this one is an error do nothing */
6593 if (tree->isError ||
6594 (tree->left && tree->left->isError) ||
6595 (tree->right && tree->right->isError)) {
6596 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6600 /* print the line */
6601 /* if not block & function */
6602 if (tree->type == EX_OP &&
6603 (tree->opval.op != FUNCTION &&
6604 tree->opval.op != BLOCK &&
6605 tree->opval.op != NULLOP)) {
6608 if (tree->opval.op == FUNCTION) {
6610 value *args=FUNC_ARGS(tree->left->opval.val->type);
6611 fprintf(outfile,"FUNCTION (%s=%p) type (",
6612 tree->left->opval.val->name, tree);
6613 printTypeChain (tree->left->opval.val->type->next,outfile);
6614 fprintf(outfile,") args (");
6617 fprintf (outfile, ", ");
6619 printTypeChain (args ? args->type : NULL, outfile);
6621 args= args ? args->next : NULL;
6623 fprintf(outfile,")\n");
6624 ast_print(tree->left,outfile,indent);
6625 ast_print(tree->right,outfile,indent);
6628 if (tree->opval.op == BLOCK) {
6629 symbol *decls = tree->values.sym;
6630 INDENT(indent,outfile);
6631 fprintf(outfile,"{\n");
6633 INDENT(indent+2,outfile);
6634 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6635 decls->name, decls);
6636 printTypeChain(decls->type,outfile);
6637 fprintf(outfile,")\n");
6639 decls = decls->next;
6641 ast_print(tree->right,outfile,indent+2);
6642 INDENT(indent,outfile);
6643 fprintf(outfile,"}\n");
6646 if (tree->opval.op == NULLOP) {
6647 ast_print(tree->left,outfile,indent);
6648 ast_print(tree->right,outfile,indent);
6651 INDENT(indent,outfile);
6653 /*------------------------------------------------------------------*/
6654 /*----------------------------*/
6655 /* leaf has been reached */
6656 /*----------------------------*/
6657 /* if this is of type value */
6658 /* just get the type */
6659 if (tree->type == EX_VALUE) {
6661 if (IS_LITERAL (tree->opval.val->etype)) {
6662 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6663 if (SPEC_USIGN (tree->opval.val->etype))
6664 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6666 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6667 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6668 floatFromVal(tree->opval.val));
6669 } else if (tree->opval.val->sym) {
6670 /* if the undefined flag is set then give error message */
6671 if (tree->opval.val->sym->undefined) {
6672 fprintf(outfile,"UNDEFINED SYMBOL ");
6674 fprintf(outfile,"SYMBOL ");
6676 fprintf(outfile,"(%s=%p @ %p)",
6677 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6680 fprintf(outfile," type (");
6681 printTypeChain(tree->ftype,outfile);
6682 fprintf(outfile,")\n");
6684 fprintf(outfile,"\n");
6689 /* if type link for the case of cast */
6690 if (tree->type == EX_LINK) {
6691 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6692 printTypeChain(tree->opval.lnk,outfile);
6693 fprintf(outfile,")\n");
6698 /* depending on type of operator do */
6700 switch (tree->opval.op) {
6701 /*------------------------------------------------------------------*/
6702 /*----------------------------*/
6704 /*----------------------------*/
6706 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6707 printTypeChain(tree->ftype,outfile);
6708 fprintf(outfile,")\n");
6709 ast_print(tree->left,outfile,indent+2);
6710 ast_print(tree->right,outfile,indent+2);
6713 /*------------------------------------------------------------------*/
6714 /*----------------------------*/
6716 /*----------------------------*/
6718 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6719 printTypeChain(tree->ftype,outfile);
6720 fprintf(outfile,")\n");
6721 ast_print(tree->left,outfile,indent+2);
6722 ast_print(tree->right,outfile,indent+2);
6725 /*------------------------------------------------------------------*/
6726 /*----------------------------*/
6727 /* struct/union pointer */
6728 /*----------------------------*/
6730 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6731 printTypeChain(tree->ftype,outfile);
6732 fprintf(outfile,")\n");
6733 ast_print(tree->left,outfile,indent+2);
6734 ast_print(tree->right,outfile,indent+2);
6737 /*------------------------------------------------------------------*/
6738 /*----------------------------*/
6739 /* ++/-- operation */
6740 /*----------------------------*/
6743 fprintf(outfile,"post-");
6745 fprintf(outfile,"pre-");
6746 fprintf(outfile,"INC_OP (%p) type (",tree);
6747 printTypeChain(tree->ftype,outfile);
6748 fprintf(outfile,")\n");
6749 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6750 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6755 fprintf(outfile,"post-");
6757 fprintf(outfile,"pre-");
6758 fprintf(outfile,"DEC_OP (%p) type (",tree);
6759 printTypeChain(tree->ftype,outfile);
6760 fprintf(outfile,")\n");
6761 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6762 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6765 /*------------------------------------------------------------------*/
6766 /*----------------------------*/
6768 /*----------------------------*/
6771 fprintf(outfile,"& (%p) type (",tree);
6772 printTypeChain(tree->ftype,outfile);
6773 fprintf(outfile,")\n");
6774 ast_print(tree->left,outfile,indent+2);
6775 ast_print(tree->right,outfile,indent+2);
6777 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6778 printTypeChain(tree->ftype,outfile);
6779 fprintf(outfile,")\n");
6780 ast_print(tree->left,outfile,indent+2);
6781 ast_print(tree->right,outfile,indent+2);
6784 /*----------------------------*/
6786 /*----------------------------*/
6788 fprintf(outfile,"OR (%p) type (",tree);
6789 printTypeChain(tree->ftype,outfile);
6790 fprintf(outfile,")\n");
6791 ast_print(tree->left,outfile,indent+2);
6792 ast_print(tree->right,outfile,indent+2);
6794 /*------------------------------------------------------------------*/
6795 /*----------------------------*/
6797 /*----------------------------*/
6799 fprintf(outfile,"XOR (%p) type (",tree);
6800 printTypeChain(tree->ftype,outfile);
6801 fprintf(outfile,")\n");
6802 ast_print(tree->left,outfile,indent+2);
6803 ast_print(tree->right,outfile,indent+2);
6806 /*------------------------------------------------------------------*/
6807 /*----------------------------*/
6809 /*----------------------------*/
6811 fprintf(outfile,"DIV (%p) type (",tree);
6812 printTypeChain(tree->ftype,outfile);
6813 fprintf(outfile,")\n");
6814 ast_print(tree->left,outfile,indent+2);
6815 ast_print(tree->right,outfile,indent+2);
6817 /*------------------------------------------------------------------*/
6818 /*----------------------------*/
6820 /*----------------------------*/
6822 fprintf(outfile,"MOD (%p) type (",tree);
6823 printTypeChain(tree->ftype,outfile);
6824 fprintf(outfile,")\n");
6825 ast_print(tree->left,outfile,indent+2);
6826 ast_print(tree->right,outfile,indent+2);
6829 /*------------------------------------------------------------------*/
6830 /*----------------------------*/
6831 /* address dereference */
6832 /*----------------------------*/
6833 case '*': /* can be unary : if right is null then unary operation */
6835 fprintf(outfile,"DEREF (%p) type (",tree);
6836 printTypeChain(tree->ftype,outfile);
6837 fprintf(outfile,")\n");
6838 ast_print(tree->left,outfile,indent+2);
6841 /*------------------------------------------------------------------*/
6842 /*----------------------------*/
6843 /* multiplication */
6844 /*----------------------------*/
6845 fprintf(outfile,"MULT (%p) type (",tree);
6846 printTypeChain(tree->ftype,outfile);
6847 fprintf(outfile,")\n");
6848 ast_print(tree->left,outfile,indent+2);
6849 ast_print(tree->right,outfile,indent+2);
6853 /*------------------------------------------------------------------*/
6854 /*----------------------------*/
6855 /* unary '+' operator */
6856 /*----------------------------*/
6860 fprintf(outfile,"UPLUS (%p) type (",tree);
6861 printTypeChain(tree->ftype,outfile);
6862 fprintf(outfile,")\n");
6863 ast_print(tree->left,outfile,indent+2);
6865 /*------------------------------------------------------------------*/
6866 /*----------------------------*/
6868 /*----------------------------*/
6869 fprintf(outfile,"ADD (%p) type (",tree);
6870 printTypeChain(tree->ftype,outfile);
6871 fprintf(outfile,")\n");
6872 ast_print(tree->left,outfile,indent+2);
6873 ast_print(tree->right,outfile,indent+2);
6876 /*------------------------------------------------------------------*/
6877 /*----------------------------*/
6879 /*----------------------------*/
6880 case '-': /* can be unary */
6882 fprintf(outfile,"UMINUS (%p) type (",tree);
6883 printTypeChain(tree->ftype,outfile);
6884 fprintf(outfile,")\n");
6885 ast_print(tree->left,outfile,indent+2);
6887 /*------------------------------------------------------------------*/
6888 /*----------------------------*/
6890 /*----------------------------*/
6891 fprintf(outfile,"SUB (%p) type (",tree);
6892 printTypeChain(tree->ftype,outfile);
6893 fprintf(outfile,")\n");
6894 ast_print(tree->left,outfile,indent+2);
6895 ast_print(tree->right,outfile,indent+2);
6898 /*------------------------------------------------------------------*/
6899 /*----------------------------*/
6901 /*----------------------------*/
6903 fprintf(outfile,"COMPL (%p) type (",tree);
6904 printTypeChain(tree->ftype,outfile);
6905 fprintf(outfile,")\n");
6906 ast_print(tree->left,outfile,indent+2);
6908 /*------------------------------------------------------------------*/
6909 /*----------------------------*/
6911 /*----------------------------*/
6913 fprintf(outfile,"NOT (%p) type (",tree);
6914 printTypeChain(tree->ftype,outfile);
6915 fprintf(outfile,")\n");
6916 ast_print(tree->left,outfile,indent+2);
6918 /*------------------------------------------------------------------*/
6919 /*----------------------------*/
6921 /*----------------------------*/
6923 fprintf(outfile,"RRC (%p) type (",tree);
6924 printTypeChain(tree->ftype,outfile);
6925 fprintf(outfile,")\n");
6926 ast_print(tree->left,outfile,indent+2);
6930 fprintf(outfile,"RLC (%p) type (",tree);
6931 printTypeChain(tree->ftype,outfile);
6932 fprintf(outfile,")\n");
6933 ast_print(tree->left,outfile,indent+2);
6936 fprintf(outfile,"SWAP (%p) type (",tree);
6937 printTypeChain(tree->ftype,outfile);
6938 fprintf(outfile,")\n");
6939 ast_print(tree->left,outfile,indent+2);
6942 fprintf(outfile,"GETHBIT (%p) type (",tree);
6943 printTypeChain(tree->ftype,outfile);
6944 fprintf(outfile,")\n");
6945 ast_print(tree->left,outfile,indent+2);
6948 fprintf(outfile,"GETABIT (%p) type (",tree);
6949 printTypeChain(tree->ftype,outfile);
6950 fprintf(outfile,")\n");
6951 ast_print(tree->left,outfile,indent+2);
6952 ast_print(tree->right,outfile,indent+2);
6955 fprintf(outfile,"GETBYTE (%p) type (",tree);
6956 printTypeChain(tree->ftype,outfile);
6957 fprintf(outfile,")\n");
6958 ast_print(tree->left,outfile,indent+2);
6959 ast_print(tree->right,outfile,indent+2);
6962 fprintf(outfile,"GETWORD (%p) type (",tree);
6963 printTypeChain(tree->ftype,outfile);
6964 fprintf(outfile,")\n");
6965 ast_print(tree->left,outfile,indent+2);
6966 ast_print(tree->right,outfile,indent+2);
6969 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6970 printTypeChain(tree->ftype,outfile);
6971 fprintf(outfile,")\n");
6972 ast_print(tree->left,outfile,indent+2);
6973 ast_print(tree->right,outfile,indent+2);
6976 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6977 printTypeChain(tree->ftype,outfile);
6978 fprintf(outfile,")\n");
6979 ast_print(tree->left,outfile,indent+2);
6980 ast_print(tree->right,outfile,indent+2);
6982 /*------------------------------------------------------------------*/
6983 /*----------------------------*/
6985 /*----------------------------*/
6986 case CAST: /* change the type */
6987 fprintf(outfile,"CAST (%p) from type (",tree);
6988 printTypeChain(tree->right->ftype,outfile);
6989 fprintf(outfile,") to type (");
6990 printTypeChain(tree->ftype,outfile);
6991 fprintf(outfile,")\n");
6992 ast_print(tree->right,outfile,indent+2);
6996 fprintf(outfile,"ANDAND (%p) type (",tree);
6997 printTypeChain(tree->ftype,outfile);
6998 fprintf(outfile,")\n");
6999 ast_print(tree->left,outfile,indent+2);
7000 ast_print(tree->right,outfile,indent+2);
7003 fprintf(outfile,"OROR (%p) type (",tree);
7004 printTypeChain(tree->ftype,outfile);
7005 fprintf(outfile,")\n");
7006 ast_print(tree->left,outfile,indent+2);
7007 ast_print(tree->right,outfile,indent+2);
7010 /*------------------------------------------------------------------*/
7011 /*----------------------------*/
7012 /* comparison operators */
7013 /*----------------------------*/
7015 fprintf(outfile,"GT(>) (%p) type (",tree);
7016 printTypeChain(tree->ftype,outfile);
7017 fprintf(outfile,")\n");
7018 ast_print(tree->left,outfile,indent+2);
7019 ast_print(tree->right,outfile,indent+2);
7022 fprintf(outfile,"LT(<) (%p) type (",tree);
7023 printTypeChain(tree->ftype,outfile);
7024 fprintf(outfile,")\n");
7025 ast_print(tree->left,outfile,indent+2);
7026 ast_print(tree->right,outfile,indent+2);
7029 fprintf(outfile,"LE(<=) (%p) type (",tree);
7030 printTypeChain(tree->ftype,outfile);
7031 fprintf(outfile,")\n");
7032 ast_print(tree->left,outfile,indent+2);
7033 ast_print(tree->right,outfile,indent+2);
7036 fprintf(outfile,"GE(>=) (%p) type (",tree);
7037 printTypeChain(tree->ftype,outfile);
7038 fprintf(outfile,")\n");
7039 ast_print(tree->left,outfile,indent+2);
7040 ast_print(tree->right,outfile,indent+2);
7043 fprintf(outfile,"EQ(==) (%p) type (",tree);
7044 printTypeChain(tree->ftype,outfile);
7045 fprintf(outfile,")\n");
7046 ast_print(tree->left,outfile,indent+2);
7047 ast_print(tree->right,outfile,indent+2);
7050 fprintf(outfile,"NE(!=) (%p) type (",tree);
7051 printTypeChain(tree->ftype,outfile);
7052 fprintf(outfile,")\n");
7053 ast_print(tree->left,outfile,indent+2);
7054 ast_print(tree->right,outfile,indent+2);
7055 /*------------------------------------------------------------------*/
7056 /*----------------------------*/
7058 /*----------------------------*/
7059 case SIZEOF: /* evaluate wihout code generation */
7060 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7063 /*------------------------------------------------------------------*/
7064 /*----------------------------*/
7065 /* conditional operator '?' */
7066 /*----------------------------*/
7068 fprintf(outfile,"QUEST(?) (%p) type (",tree);
7069 printTypeChain(tree->ftype,outfile);
7070 fprintf(outfile,")\n");
7071 ast_print(tree->left,outfile,indent+2);
7072 ast_print(tree->right,outfile,indent+2);
7076 fprintf(outfile,"COLON(:) (%p) type (",tree);
7077 printTypeChain(tree->ftype,outfile);
7078 fprintf(outfile,")\n");
7079 ast_print(tree->left,outfile,indent+2);
7080 ast_print(tree->right,outfile,indent+2);
7083 /*------------------------------------------------------------------*/
7084 /*----------------------------*/
7085 /* assignment operators */
7086 /*----------------------------*/
7088 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7089 printTypeChain(tree->ftype,outfile);
7090 fprintf(outfile,")\n");
7091 ast_print(tree->left,outfile,indent+2);
7092 ast_print(tree->right,outfile,indent+2);
7095 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7096 printTypeChain(tree->ftype,outfile);
7097 fprintf(outfile,")\n");
7098 ast_print(tree->left,outfile,indent+2);
7099 ast_print(tree->right,outfile,indent+2);
7102 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7103 printTypeChain(tree->ftype,outfile);
7104 fprintf(outfile,")\n");
7105 ast_print(tree->left,outfile,indent+2);
7106 ast_print(tree->right,outfile,indent+2);
7109 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7110 printTypeChain(tree->ftype,outfile);
7111 fprintf(outfile,")\n");
7112 ast_print(tree->left,outfile,indent+2);
7113 ast_print(tree->right,outfile,indent+2);
7116 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7117 printTypeChain(tree->ftype,outfile);
7118 fprintf(outfile,")\n");
7119 ast_print(tree->left,outfile,indent+2);
7120 ast_print(tree->right,outfile,indent+2);
7123 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7124 printTypeChain(tree->ftype,outfile);
7125 fprintf(outfile,")\n");
7126 ast_print(tree->left,outfile,indent+2);
7127 ast_print(tree->right,outfile,indent+2);
7130 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7131 printTypeChain(tree->ftype,outfile);
7132 fprintf(outfile,")\n");
7133 ast_print(tree->left,outfile,indent+2);
7134 ast_print(tree->right,outfile,indent+2);
7136 /*------------------------------------------------------------------*/
7137 /*----------------------------*/
7139 /*----------------------------*/
7141 fprintf(outfile,"SUBASS(-=) (%p) type (",tree);
7142 printTypeChain(tree->ftype,outfile);
7143 fprintf(outfile,")\n");
7144 ast_print(tree->left,outfile,indent+2);
7145 ast_print(tree->right,outfile,indent+2);
7147 /*------------------------------------------------------------------*/
7148 /*----------------------------*/
7150 /*----------------------------*/
7152 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7153 printTypeChain(tree->ftype,outfile);
7154 fprintf(outfile,")\n");
7155 ast_print(tree->left,outfile,indent+2);
7156 ast_print(tree->right,outfile,indent+2);
7158 /*------------------------------------------------------------------*/
7159 /*----------------------------*/
7160 /* straight assignemnt */
7161 /*----------------------------*/
7163 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7164 printTypeChain(tree->ftype,outfile);
7165 fprintf(outfile,")\n");
7166 ast_print(tree->left,outfile,indent+2);
7167 ast_print(tree->right,outfile,indent+2);
7169 /*------------------------------------------------------------------*/
7170 /*----------------------------*/
7171 /* comma operator */
7172 /*----------------------------*/
7174 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7175 printTypeChain(tree->ftype,outfile);
7176 fprintf(outfile,")\n");
7177 ast_print(tree->left,outfile,indent+2);
7178 ast_print(tree->right,outfile,indent+2);
7180 /*------------------------------------------------------------------*/
7181 /*----------------------------*/
7183 /*----------------------------*/
7186 fprintf(outfile,"CALL (%p) type (",tree);
7187 printTypeChain(tree->ftype,outfile);
7188 fprintf(outfile,")\n");
7189 ast_print(tree->left,outfile,indent+2);
7190 ast_print(tree->right,outfile,indent+2);
7193 fprintf(outfile,"PARMS\n");
7194 ast_print(tree->left,outfile,indent+2);
7195 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7196 ast_print(tree->right,outfile,indent+2);
7199 /*------------------------------------------------------------------*/
7200 /*----------------------------*/
7201 /* return statement */
7202 /*----------------------------*/
7204 fprintf(outfile,"RETURN (%p) type (",tree);
7206 printTypeChain(tree->right->ftype,outfile);
7208 fprintf(outfile,")\n");
7209 ast_print(tree->right,outfile,indent+2);
7211 /*------------------------------------------------------------------*/
7212 /*----------------------------*/
7213 /* label statement */
7214 /*----------------------------*/
7216 fprintf(outfile,"LABEL (%p)\n",tree);
7217 ast_print(tree->left,outfile,indent+2);
7218 ast_print(tree->right,outfile,indent);
7220 /*------------------------------------------------------------------*/
7221 /*----------------------------*/
7222 /* switch statement */
7223 /*----------------------------*/
7227 fprintf(outfile,"SWITCH (%p) ",tree);
7228 ast_print(tree->left,outfile,0);
7229 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7230 INDENT(indent+2,outfile);
7231 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7232 (int) ulFromVal(val),
7233 tree->values.switchVals.swNum,
7234 (int) ulFromVal(val));
7236 ast_print(tree->right,outfile,indent);
7239 /*------------------------------------------------------------------*/
7240 /*----------------------------*/
7242 /*----------------------------*/
7244 fprintf(outfile,"IF (%p) \n",tree);
7245 ast_print(tree->left,outfile,indent+2);
7246 if (tree->trueLabel) {
7247 INDENT(indent+2,outfile);
7248 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7250 if (tree->falseLabel) {
7251 INDENT(indent+2,outfile);
7252 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7254 ast_print(tree->right,outfile,indent+2);
7256 /*----------------------------*/
7257 /* goto Statement */
7258 /*----------------------------*/
7260 fprintf(outfile,"GOTO (%p) \n",tree);
7261 ast_print(tree->left,outfile,indent+2);
7262 fprintf(outfile,"\n");
7264 /*------------------------------------------------------------------*/
7265 /*----------------------------*/
7267 /*----------------------------*/
7269 fprintf(outfile,"FOR (%p) \n",tree);
7270 if (AST_FOR( tree, initExpr)) {
7271 INDENT(indent+2,outfile);
7272 fprintf(outfile,"INIT EXPR ");
7273 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7275 if (AST_FOR( tree, condExpr)) {
7276 INDENT(indent+2,outfile);
7277 fprintf(outfile,"COND EXPR ");
7278 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7280 if (AST_FOR( tree, loopExpr)) {
7281 INDENT(indent+2,outfile);
7282 fprintf(outfile,"LOOP EXPR ");
7283 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7285 fprintf(outfile,"FOR LOOP BODY \n");
7286 ast_print(tree->left,outfile,indent+2);
7289 fprintf(outfile,"CRITICAL (%p) \n",tree);
7290 ast_print(tree->left,outfile,indent+2);
7298 ast_print(t,stdout,0);
7301 /*-----------------------------------------------------------------*/
7302 /* astErrors : returns non-zero if errors present in tree */
7303 /*-----------------------------------------------------------------*/
7304 int astErrors(ast *t)
7313 if (t->type == EX_VALUE
7314 && t->opval.val->sym
7315 && t->opval.val->sym->undefined)
7318 errors += astErrors(t->left);
7319 errors += astErrors(t->right);