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)
87 static int oldLineno = 0;
89 ex = Safe_alloc ( sizeof (ast));
92 ex->lineno = (noLineno ? oldLineno : lexLineno);
93 ex->filename = lexFilename;
94 ex->level = NestLevel;
95 ex->block = currBlockno;
96 ex->initMode = inInitMode;
97 ex->seqPoint = seqPointNo;
102 newAst_VALUE (value * val)
104 ast *ex = newAst_ (EX_VALUE);
110 newAst_OP (unsigned op)
112 ast *ex = newAst_ (EX_OP);
118 newAst_LINK (sym_link * val)
120 ast *ex = newAst_ (EX_LINK);
125 /*-----------------------------------------------------------------*/
126 /* newNode - creates a new node */
127 /*-----------------------------------------------------------------*/
129 newNode (long op, ast * left, ast * right)
140 /*-----------------------------------------------------------------*/
141 /* newIfxNode - creates a new Ifx Node */
142 /*-----------------------------------------------------------------*/
144 newIfxNode (ast * condAst, symbol * trueLabel, symbol * falseLabel)
148 /* if this is a literal then we already know the result */
149 if (condAst->etype && IS_LITERAL (condAst->etype))
151 /* then depending on the expression value */
152 if (floatFromVal (condAst->opval.val))
153 ifxNode = newNode (GOTO,
154 newAst_VALUE (symbolVal (trueLabel)),
157 ifxNode = newNode (GOTO,
158 newAst_VALUE (symbolVal (falseLabel)),
163 ifxNode = newNode (IFX, condAst, NULL);
164 ifxNode->trueLabel = trueLabel;
165 ifxNode->falseLabel = falseLabel;
171 /*-----------------------------------------------------------------*/
172 /* copyAstValues - copies value portion of ast if needed */
173 /*-----------------------------------------------------------------*/
175 copyAstValues (ast * dest, ast * src)
177 switch (src->opval.op)
180 dest->values.sym = copySymbolChain (src->values.sym);
184 dest->values.switchVals.swVals =
185 copyValue (src->values.switchVals.swVals);
186 dest->values.switchVals.swDefault =
187 src->values.switchVals.swDefault;
188 dest->values.switchVals.swNum =
189 src->values.switchVals.swNum;
193 dest->values.inlineasm = Safe_strdup(src->values.inlineasm);
197 dest->values.constlist = copyLiteralList(src->values.constlist);
201 AST_FOR (dest, trueLabel) = copySymbol (AST_FOR (src, trueLabel));
202 AST_FOR (dest, continueLabel) = copySymbol (AST_FOR (src, continueLabel));
203 AST_FOR (dest, falseLabel) = copySymbol (AST_FOR (src, falseLabel));
204 AST_FOR (dest, condLabel) = copySymbol (AST_FOR (src, condLabel));
205 AST_FOR (dest, initExpr) = copyAst (AST_FOR (src, initExpr));
206 AST_FOR (dest, condExpr) = copyAst (AST_FOR (src, condExpr));
207 AST_FOR (dest, loopExpr) = copyAst (AST_FOR (src, loopExpr));
212 /*-----------------------------------------------------------------*/
213 /* copyAst - makes a copy of a given astession */
214 /*-----------------------------------------------------------------*/
223 dest = Safe_alloc ( sizeof (ast));
225 dest->type = src->type;
226 dest->lineno = src->lineno;
227 dest->level = src->level;
228 dest->funcName = src->funcName;
229 dest->reversed = src->reversed;
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));
395 /* we would have to handle '.', but it is not generated any more */
396 wassertl(target->opval.op != '.', "obsolete opcode in tree");
398 /* no other kinds of ASTs are lvalues and can contain side effects */
403 writeval = copyAst(target);
405 result = newNode('=', writeval, newNode(op, readval, operand));
407 result = newNode(',', tempvar2, result);
409 result = newNode(',', tempvar1, result);
415 /*-----------------------------------------------------------------*/
416 /* hasSEFcalls - returns TRUE if tree has a function call, */
417 /* inc/decrement, or other side effect */
418 /*-----------------------------------------------------------------*/
420 hasSEFcalls (ast * tree)
425 if (tree->type == EX_OP &&
426 (tree->opval.op == CALL ||
427 tree->opval.op == PCALL ||
428 tree->opval.op == '=' ||
429 tree->opval.op == INC_OP ||
430 tree->opval.op == DEC_OP))
433 return (hasSEFcalls (tree->left) |
434 hasSEFcalls (tree->right));
437 /*-----------------------------------------------------------------*/
438 /* isAstEqual - compares two asts & returns 1 if they are equal */
439 /*-----------------------------------------------------------------*/
441 isAstEqual (ast * t1, ast * t2)
450 if (t1->type != t2->type)
456 if (t1->opval.op != t2->opval.op)
458 return (isAstEqual (t1->left, t2->left) &&
459 isAstEqual (t1->right, t2->right));
463 if (t1->opval.val->sym)
465 if (!t2->opval.val->sym)
468 return isSymbolEqual (t1->opval.val->sym,
473 if (t2->opval.val->sym)
476 return (floatFromVal (t1->opval.val) ==
477 floatFromVal (t2->opval.val));
481 /* only compare these two types */
489 /*-----------------------------------------------------------------*/
490 /* resolveSymbols - resolve symbols from the symbol table */
491 /*-----------------------------------------------------------------*/
493 resolveSymbols (ast * tree)
495 /* walk the entire tree and check for values */
496 /* with symbols if we find one then replace */
497 /* symbol with that from the symbol table */
504 /* if not block & function */
505 if (tree->type == EX_OP &&
506 (tree->opval.op != FUNCTION &&
507 tree->opval.op != BLOCK &&
508 tree->opval.op != NULLOP))
510 filename = tree->filename;
511 lineno = tree->lineno;
515 /* make sure we resolve the true & false labels for ifx */
516 if (tree->type == EX_OP && tree->opval.op == IFX)
522 if ((csym = findSym (LabelTab, tree->trueLabel,
523 tree->trueLabel->name)))
524 tree->trueLabel = csym;
526 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
527 tree->trueLabel->name);
530 if (tree->falseLabel)
532 if ((csym = findSym (LabelTab,
534 tree->falseLabel->name)))
535 tree->falseLabel = csym;
537 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
538 tree->falseLabel->name);
543 /* if this is a label resolve it from the labelTab */
544 if (IS_AST_VALUE (tree) &&
545 tree->opval.val->sym &&
546 tree->opval.val->sym->islbl)
549 symbol *csym = findSym (LabelTab, tree->opval.val->sym,
550 tree->opval.val->sym->name);
553 werrorfl (tree->filename, tree->lineno, E_LABEL_UNDEF,
554 tree->opval.val->sym->name);
556 tree->opval.val->sym = csym;
558 goto resolveChildren;
561 /* do only for leafs */
562 if (IS_AST_VALUE (tree) &&
563 tree->opval.val->sym &&
564 !tree->opval.val->sym->implicit)
567 symbol *csym = findSymWithLevel (SymbolTab, tree->opval.val->sym);
569 /* if found in the symbol table & they r 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 is */
579 /* an integer in data space */
580 if (!csym && !tree->opval.val->sym->implicit)
583 /* if this is a function name then */
584 /* mark it as returning an int */
587 tree->opval.val->sym->type = newLink (DECLARATOR);
588 DCL_TYPE (tree->opval.val->sym->type) = FUNCTION;
589 tree->opval.val->sym->type->next =
590 tree->opval.val->sym->etype = newIntLink ();
591 tree->opval.val->etype = tree->opval.val->etype;
592 tree->opval.val->type = tree->opval.val->sym->type;
593 werrorfl (tree->filename, tree->lineno, W_IMPLICIT_FUNC,
594 tree->opval.val->sym->name);
595 //tree->opval.val->sym->undefined = 1;
596 allocVariables (tree->opval.val->sym);
600 tree->opval.val->sym->undefined = 1;
601 tree->opval.val->type =
602 tree->opval.val->etype = newIntLink ();
603 tree->opval.val->sym->type =
604 tree->opval.val->sym->etype = newIntLink ();
610 resolveSymbols (tree->left);
611 resolveSymbols (tree->right);
616 /*-----------------------------------------------------------------*/
617 /* setAstLineno - walks a ast tree & sets the line number */
618 /*-----------------------------------------------------------------*/
619 int setAstLineno (ast * tree, int lineno)
624 tree->lineno = lineno;
625 setAstLineno (tree->left, lineno);
626 setAstLineno (tree->right, 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 a 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 (W_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 if (IS_CAST_OP (*actParm)
854 || (IS_AST_LIT_VALUE (*actParm) && (*actParm)->values.literalFromCast))
856 /* Parameter was explicitly typecast; don't touch it. */
860 ftype = (*actParm)->ftype;
862 /* If it's a char, upcast to int. */
863 if (IS_INTEGRAL (ftype)
864 && (getSize (ftype) < (unsigned) INTSIZE))
866 newType = newAst_LINK(INTTYPE);
869 if (IS_PTR(ftype) && !IS_GENPTR(ftype))
871 newType = newAst_LINK (copyLinkChain(ftype));
872 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
875 if (IS_AGGREGATE (ftype))
877 newType = newAst_LINK (copyLinkChain (ftype));
878 DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer;
883 /* cast required; change this op to a cast. */
884 (*actParm)->decorated = 0;
885 *actParm = newNode (CAST, newType, *actParm);
886 (*actParm)->lineno = (*actParm)->right->lineno;
888 decorateType (*actParm, RESULT_TYPE_NONE);
893 /* if defined parameters ended but actual has not & */
895 if (!defParm && *actParm &&
896 (options.stackAuto || IFFUNC_ISREENT (functype)))
899 resolveSymbols (*actParm);
901 /* the parameter type must be at least castable */
902 if (compareType (defParm->type, (*actParm)->ftype) == 0)
904 werror (E_INCOMPAT_TYPES);
905 printFromToType ((*actParm)->ftype, defParm->type);
909 /* if the parameter is castable then add the cast */
910 if (compareType (defParm->type, (*actParm)->ftype) < 0)
914 resultType = getResultTypeFromType (defParm->etype);
915 pTree = resolveSymbols (copyAst (*actParm));
917 /* now change the current one to a cast */
918 (*actParm)->type = EX_OP;
919 (*actParm)->opval.op = CAST;
920 (*actParm)->left = newAst_LINK (defParm->type);
921 (*actParm)->right = pTree;
922 (*actParm)->decorated = 0; /* force typechecking */
923 decorateType (*actParm, resultType);
926 /* make a copy and change the regparm type to the defined parm */
927 (*actParm)->etype = getSpec ((*actParm)->ftype = copyLinkChain ((*actParm)->ftype));
928 SPEC_REGPARM ((*actParm)->etype) = SPEC_REGPARM (defParm->etype);
929 SPEC_ARGREG ((*actParm)->etype) = SPEC_ARGREG (defParm->etype);
934 /*-----------------------------------------------------------------*/
935 /* createIvalType - generates ival for basic types */
936 /*-----------------------------------------------------------------*/
938 createIvalType (ast * sym, sym_link * type, initList * ilist)
942 /* if initList is deep */
943 if (ilist->type == INIT_DEEP)
944 ilist = ilist->init.deep;
946 iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
947 return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
950 /*-----------------------------------------------------------------*/
951 /* createIvalStruct - generates initial value for structures */
952 /*-----------------------------------------------------------------*/
954 createIvalStruct (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
961 sflds = SPEC_STRUCT (type)->fields;
962 if (ilist->type != INIT_DEEP)
964 werror (E_INIT_STRUCT, "");
968 iloop = ilist->init.deep;
970 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
972 /* if we have come to end */
976 lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
977 lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
978 rast = decorateType (resolveSymbols (createIval (lAst, sflds->type,
979 iloop, rast, rootValue)),
985 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
986 W_EXCESS_INITIALIZERS, "struct",
987 sym->opval.val->sym->name);
994 /*-----------------------------------------------------------------*/
995 /* createIvalArray - generates code for array initialization */
996 /*-----------------------------------------------------------------*/
998 createIvalArray (ast * sym, sym_link * type, initList * ilist, ast *rootValue)
1002 int lcnt = 0, size = 0;
1003 literalList *literalL;
1005 /* take care of the special case */
1006 /* array of characters can be init */
1008 if (IS_CHAR (type->next))
1009 if ((rast = createIvalCharPtr (sym,
1011 decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE),
1014 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1016 /* not the special case */
1017 if (ilist->type != INIT_DEEP)
1019 werror (E_INIT_STRUCT, "");
1023 iloop = ilist->init.deep;
1024 lcnt = DCL_ELEM (type);
1026 if (port->arrayInitializerSuppported && convertIListToConstList(ilist, &literalL))
1030 aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
1032 rast = newNode(ARRAYINIT, aSym, NULL);
1033 rast->values.constlist = literalL;
1035 // Make sure size is set to length of initializer list.
1039 iloop = iloop->next;
1042 if (lcnt && size > lcnt)
1044 // Array size was specified, and we have more initializers than needed.
1045 werrorfl (sym->opval.val->sym->fileDef, sym->opval.val->sym->lineDef,
1046 W_EXCESS_INITIALIZERS, "array", sym->opval.val->sym->name);
1055 aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
1056 aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
1057 rast = createIval (aSym, type->next, iloop, rast, rootValue);
1058 iloop = (iloop ? iloop->next : NULL);
1064 /* no of elements given and we */
1065 /* have generated for all of them */
1068 // is this a better way? at least it won't crash
1069 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1070 werrorfl (iloop->filename, iloop->lineno, W_EXCESS_INITIALIZERS, "array", name);
1077 /* if we have not been given a size */
1078 if (!DCL_ELEM (type))
1080 /* check, if it's a flexible array */
1081 if (IS_STRUCT (AST_VALUE (rootValue)->type))
1082 AST_SYMBOL(rootValue)->flexArrayLength = size * getSize (type->next);
1084 DCL_ELEM (type) = size;
1087 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1091 /*-----------------------------------------------------------------*/
1092 /* createIvalCharPtr - generates initial values for char pointers */
1093 /*-----------------------------------------------------------------*/
1095 createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr, ast *rootVal)
1100 /* if this is a pointer & right is a literal array then */
1101 /* just assignment will do */
1102 if (IS_PTR (type) && ((IS_LITERAL (iexpr->etype) ||
1103 SPEC_SCLS (iexpr->etype) == S_CODE)
1104 && IS_ARRAY (iexpr->ftype)))
1105 return newNode ('=', sym, iexpr);
1107 /* left side is an array so we have to assign each */
1109 if ((IS_LITERAL (iexpr->etype) ||
1110 SPEC_SCLS (iexpr->etype) == S_CODE)
1111 && IS_ARRAY (iexpr->ftype))
1113 /* for each character generate an assignment */
1114 /* to the array element */
1115 char *s = SPEC_CVAL (iexpr->etype).v_char;
1117 unsigned int symsize = getSize (type);
1119 size = getSize (iexpr->ftype);
1120 if (symsize && size>symsize)
1122 if (size>(symsize+1))
1124 char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
1126 werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
1132 for (i=0;i<size;i++)
1134 rast = newNode (NULLOP,
1138 newAst_VALUE (valueFromLit ((float) i))),
1139 newAst_VALUE (valueFromLit (*s))));
1143 // now WE don't need iexpr's symbol anymore
1144 freeStringSymbol(AST_SYMBOL(iexpr));
1146 /* if we have not been given a size */
1147 if (!DCL_ELEM (type))
1149 /* check, if it's a flexible array */
1150 if (IS_STRUCT (AST_VALUE (rootVal)->type))
1151 AST_SYMBOL(rootVal)->flexArrayLength = size * getSize (type->next);
1153 DCL_ELEM (type) = size;
1156 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1162 /*-----------------------------------------------------------------*/
1163 /* createIvalPtr - generates initial value for pointers */
1164 /*-----------------------------------------------------------------*/
1166 createIvalPtr (ast * sym, sym_link * type, initList * ilist, ast *rootVal)
1172 if (ilist->type == INIT_DEEP)
1173 ilist = ilist->init.deep;
1175 iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
1177 /* if character pointer */
1178 if (IS_CHAR (type->next))
1179 if ((rast = createIvalCharPtr (sym, type, iexpr, rootVal)))
1182 return newNode ('=', sym, iexpr);
1185 /*-----------------------------------------------------------------*/
1186 /* createIval - generates code for initial value */
1187 /*-----------------------------------------------------------------*/
1189 createIval (ast * sym, sym_link * type, initList * ilist, ast * wid, ast *rootValue)
1196 /* if structure then */
1197 if (IS_STRUCT (type))
1198 rast = createIvalStruct (sym, type, ilist, rootValue);
1200 /* if this is a pointer */
1202 rast = createIvalPtr (sym, type, ilist, rootValue);
1204 /* if this is an array */
1205 if (IS_ARRAY (type))
1206 rast = createIvalArray (sym, type, ilist, rootValue);
1208 /* if type is SPECIFIER */
1210 rast = createIvalType (sym, type, ilist);
1213 return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
1215 return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
1218 /*-----------------------------------------------------------------*/
1219 /* initAggregates - initialises aggregate variables with initv */
1220 /*-----------------------------------------------------------------*/
1221 ast * initAggregates (symbol * sym, initList * ival, ast * wid) {
1222 ast *newAst = newAst_VALUE (symbolVal (sym));
1223 return createIval (newAst, sym->type, ival, wid, newAst);
1226 /*-----------------------------------------------------------------*/
1227 /* gatherAutoInit - creates assignment expressions for initial */
1229 /*-----------------------------------------------------------------*/
1231 gatherAutoInit (symbol * autoChain)
1238 for (sym = autoChain; sym; sym = sym->next)
1241 /* resolve the symbols in the ival */
1243 resolveIvalSym (sym->ival, sym->type);
1246 /* if we are PIC16 port,
1247 * and this is a static,
1248 * and have initial value,
1249 * and not S_CODE, don't emit in gs segment,
1250 * but allow glue.c:pic16emitRegularMap to put symbol
1251 * in idata section */
1252 if(TARGET_IS_PIC16 &&
1253 IS_STATIC (sym->etype) && sym->ival
1254 && SPEC_SCLS(sym->etype) != S_CODE) {
1255 SPEC_SCLS (sym->etype) = S_DATA;
1260 /* if this is a static variable & has an */
1261 /* initial value the code needs to be lifted */
1262 /* here to the main portion since they can be */
1263 /* initialised only once at the start */
1264 if (IS_STATIC (sym->etype) && sym->ival &&
1265 SPEC_SCLS (sym->etype) != S_CODE)
1269 /* insert the symbol into the symbol table */
1270 /* with level = 0 & name = rname */
1271 newSym = copySymbol (sym);
1272 addSym (SymbolTab, newSym, newSym->rname, 0, 0, 1);
1274 /* now lift the code to main */
1275 if (IS_AGGREGATE (sym->type)) {
1276 work = initAggregates (sym, sym->ival, NULL);
1278 if (getNelements(sym->type, sym->ival)>1) {
1279 werrorfl (sym->fileDef, sym->lineDef,
1280 W_EXCESS_INITIALIZERS, "scalar",
1283 work = newNode ('=', newAst_VALUE (symbolVal (newSym)),
1284 list2expr (sym->ival));
1287 setAstLineno (work, sym->lineDef);
1291 staticAutos = newNode (NULLOP, staticAutos, work);
1298 /* if there is an initial value */
1299 if (sym->ival && SPEC_SCLS (sym->etype) != S_CODE)
1301 initList *ilist=sym->ival;
1303 while (ilist->type == INIT_DEEP) {
1304 ilist = ilist->init.deep;
1307 /* update lineno for error msg */
1308 lineno = sym->lineDef;
1309 setAstLineno (ilist->init.node, sym->lineDef);
1311 if (IS_AGGREGATE (sym->type)) {
1312 work = initAggregates (sym, sym->ival, NULL);
1314 if (getNelements(sym->type, sym->ival)>1) {
1315 werrorfl (sym->fileDef, sym->lineDef,
1316 W_EXCESS_INITIALIZERS, "scalar",
1319 work = newNode ('=', newAst_VALUE (symbolVal (sym)),
1320 list2expr (sym->ival));
1324 setAstLineno (work, sym->lineDef);
1328 init = newNode (NULLOP, init, work);
1337 /*-----------------------------------------------------------------*/
1338 /* freeStringSymbol - delete a literal string if no more usage */
1339 /*-----------------------------------------------------------------*/
1340 void freeStringSymbol(symbol *sym) {
1341 /* make sure this is a literal string */
1342 assert (sym->isstrlit);
1343 if (--sym->isstrlit == 0) { // lower the usage count
1344 memmap *segment=SPEC_OCLS(sym->etype);
1346 deleteSetItem(&segment->syms, sym);
1351 /*-----------------------------------------------------------------*/
1352 /* stringToSymbol - creates a symbol from a literal string */
1353 /*-----------------------------------------------------------------*/
1355 stringToSymbol (value * val)
1357 char name[SDCC_NAME_MAX + 1];
1358 static int charLbl = 0;
1363 // have we heard this before?
1364 for (sp=statsg->syms; sp; sp=sp->next) {
1366 size = getSize (sym->type);
1367 if (sym->isstrlit && size == getSize (val->type) &&
1368 !memcmp(SPEC_CVAL(sym->etype).v_char, SPEC_CVAL(val->etype).v_char, size)) {
1369 // yes, this is old news. Don't publish it again.
1370 sym->isstrlit++; // but raise the usage count
1371 return symbolVal(sym);
1375 SNPRINTF (name, sizeof(name), "_str_%d", charLbl++);
1376 sym = newSymbol (name, 0); /* make it @ level 0 */
1377 strncpyz (sym->rname, name, SDCC_NAME_MAX);
1379 /* copy the type from the value passed */
1380 sym->type = copyLinkChain (val->type);
1381 sym->etype = getSpec (sym->type);
1382 /* change to storage class & output class */
1383 SPEC_SCLS (sym->etype) = S_CODE;
1384 SPEC_CVAL (sym->etype).v_char = SPEC_CVAL (val->etype).v_char;
1385 SPEC_STAT (sym->etype) = 1;
1386 /* make the level & block = 0 */
1387 sym->block = sym->level = 0;
1389 /* create an ival */
1390 sym->ival = newiList (INIT_NODE, newAst_VALUE (val));
1395 allocVariables (sym);
1398 return symbolVal (sym);
1402 /*-----------------------------------------------------------------*/
1403 /* processBlockVars - will go thru the ast looking for block if */
1404 /* a block is found then will allocate the syms */
1405 /* will also gather the auto inits present */
1406 /*-----------------------------------------------------------------*/
1408 processBlockVars (ast * tree, int *stack, int action)
1413 /* if this is a block */
1414 if (tree->type == EX_OP && tree->opval.op == BLOCK)
1418 if (action == ALLOCATE)
1420 *stack += allocVariables (tree->values.sym);
1421 autoInit = gatherAutoInit (tree->values.sym);
1423 /* if there are auto inits then do them */
1425 tree->left = newNode (NULLOP, autoInit, tree->left);
1427 else /* action is deallocate */
1428 deallocLocal (tree->values.sym);
1431 processBlockVars (tree->left, stack, action);
1432 processBlockVars (tree->right, stack, action);
1437 /*-------------------------------------------------------------*/
1438 /* constExprTree - returns TRUE if this tree is a constant */
1440 /*-------------------------------------------------------------*/
1441 bool constExprTree (ast *cexpr) {
1447 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1449 switch (cexpr->type)
1452 if (IS_AST_LIT_VALUE(cexpr)) {
1453 // this is a literal
1456 if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
1457 // a function's address will never change
1460 if (IS_AST_SYM_VALUE(cexpr) && IS_ARRAY(AST_SYMBOL(cexpr)->type)) {
1461 // an array's address will never change
1464 if (IS_AST_SYM_VALUE(cexpr) &&
1465 IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
1466 // a symbol in code space will never change
1467 // This is only for the 'char *s="hallo"' case and will have to leave
1468 //printf(" code space symbol");
1473 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1474 "unexpected link in expression tree\n");
1477 if (cexpr->opval.op==ARRAYINIT) {
1478 // this is a list of literals
1481 if (cexpr->opval.op=='=') {
1482 return constExprTree(cexpr->right);
1484 if (cexpr->opval.op==CAST) {
1485 // cast ignored, maybe we should throw a warning here?
1486 return constExprTree(cexpr->right);
1488 if (cexpr->opval.op=='&') {
1491 if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
1494 if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
1499 return IS_CONSTANT(operandType(cexpr->opval.oprnd));
1504 /*-----------------------------------------------------------------*/
1505 /* constExprValue - returns the value of a constant expression */
1506 /* or NULL if it is not a constant expression */
1507 /*-----------------------------------------------------------------*/
1509 constExprValue (ast * cexpr, int check)
1511 cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
1513 /* if this is not a constant then */
1514 if (!IS_LITERAL (cexpr->ftype))
1516 /* then check if this is a literal array
1518 if (SPEC_SCLS (cexpr->etype) == S_CODE &&
1519 SPEC_CVAL (cexpr->etype).v_char &&
1520 IS_ARRAY (cexpr->ftype))
1522 value *val = valFromType (cexpr->ftype);
1523 SPEC_SCLS (val->etype) = S_LITERAL;
1524 val->sym = cexpr->opval.val->sym;
1525 val->sym->type = copyLinkChain (cexpr->ftype);
1526 val->sym->etype = getSpec (val->sym->type);
1527 strncpyz (val->name, cexpr->opval.val->sym->rname, SDCC_NAME_MAX);
1531 /* if we are casting a literal value then */
1532 if (IS_AST_OP (cexpr) &&
1533 cexpr->opval.op == CAST &&
1534 IS_LITERAL (cexpr->right->ftype))
1536 return valCastLiteral (cexpr->ftype,
1537 floatFromVal (cexpr->right->opval.val));
1540 if (IS_AST_VALUE (cexpr))
1542 return cexpr->opval.val;
1546 werror (E_CONST_EXPECTED, "found expression");
1551 /* return the value */
1552 if (IS_AST_VALUE (cexpr))
1554 return cexpr->opval.val;
1559 /*-----------------------------------------------------------------*/
1560 /* isLabelInAst - will return true if a given label is found */
1561 /*-----------------------------------------------------------------*/
1563 isLabelInAst (symbol * label, ast * tree)
1565 if (!tree || IS_AST_VALUE (tree) || IS_AST_LINK (tree))
1568 if (IS_AST_OP (tree) &&
1569 tree->opval.op == LABEL &&
1570 isSymbolEqual (AST_SYMBOL (tree->left), label))
1573 return isLabelInAst (label, tree->right) &&
1574 isLabelInAst (label, tree->left);
1578 /*-----------------------------------------------------------------*/
1579 /* isLoopCountable - return true if the loop count can be determi- */
1580 /* -ned at compile time . */
1581 /*-----------------------------------------------------------------*/
1583 isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
1584 symbol ** sym, ast ** init, ast ** end)
1587 /* the loop is considered countable if the following
1588 conditions are true :-
1590 a) initExpr :- <sym> = <const>
1591 b) condExpr :- <sym> < <const1>
1592 c) loopExpr :- <sym> ++
1595 /* first check the initExpr */
1596 if (IS_AST_OP (initExpr) &&
1597 initExpr->opval.op == '=' && /* is assignment */
1598 IS_AST_SYM_VALUE (initExpr->left))
1599 { /* left is a symbol */
1601 *sym = AST_SYMBOL (initExpr->left);
1602 *init = initExpr->right;
1607 /* don't reverse loop with volatile counter */
1608 if (IS_VOLATILE ((*sym)->type))
1611 /* for now the symbol has to be of
1613 if (!IS_INTEGRAL ((*sym)->type))
1616 /* now check condExpr */
1617 if (IS_AST_OP (condExpr))
1620 switch (condExpr->opval.op)
1623 if (IS_AST_SYM_VALUE (condExpr->left) &&
1624 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left)) &&
1625 IS_AST_LIT_VALUE (condExpr->right))
1627 *end = condExpr->right;
1633 if (IS_AST_OP (condExpr->left) &&
1634 condExpr->left->opval.op == '>' &&
1635 IS_AST_LIT_VALUE (condExpr->left->right) &&
1636 IS_AST_SYM_VALUE (condExpr->left->left) &&
1637 isSymbolEqual (*sym, AST_SYMBOL (condExpr->left->left)))
1640 *end = newNode ('+', condExpr->left->right,
1641 newAst_VALUE (constVal ("1")));
1654 /* check loop expression is of the form <sym>++ */
1655 if (!IS_AST_OP (loopExpr))
1658 /* check if <sym> ++ */
1659 if (loopExpr->opval.op == INC_OP)
1665 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1666 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)))
1673 if (IS_AST_SYM_VALUE (loopExpr->right) &&
1674 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->right)))
1682 if (loopExpr->opval.op == ADD_ASSIGN)
1685 if (IS_AST_SYM_VALUE (loopExpr->left) &&
1686 isSymbolEqual (*sym, AST_SYMBOL (loopExpr->left)) &&
1687 IS_AST_LIT_VALUE (loopExpr->right) &&
1688 AST_ULONG_VALUE (loopExpr->right) != 1)
1696 /*-----------------------------------------------------------------*/
1697 /* astHasVolatile - returns true if ast contains any volatile */
1698 /*-----------------------------------------------------------------*/
1700 astHasVolatile (ast * tree)
1705 if (TETYPE (tree) && IS_VOLATILE (TETYPE (tree)))
1708 if (IS_AST_OP (tree))
1709 return astHasVolatile (tree->left) ||
1710 astHasVolatile (tree->right);
1715 /*-----------------------------------------------------------------*/
1716 /* astHasPointer - return true if the ast contains any ptr variable */
1717 /*-----------------------------------------------------------------*/
1719 astHasPointer (ast * tree)
1724 if (IS_AST_LINK (tree))
1727 /* if we hit an array expression then check
1728 only the left side */
1729 if (IS_AST_OP (tree) && tree->opval.op == '[')
1730 return astHasPointer (tree->left);
1732 if (IS_AST_VALUE (tree))
1733 return IS_PTR (tree->ftype) || IS_ARRAY (tree->ftype);
1735 return astHasPointer (tree->left) ||
1736 astHasPointer (tree->right);
1740 /*-----------------------------------------------------------------*/
1741 /* astHasSymbol - return true if the ast has the given symbol */
1742 /*-----------------------------------------------------------------*/
1744 astHasSymbol (ast * tree, symbol * sym)
1746 if (!tree || IS_AST_LINK (tree))
1749 if (IS_AST_VALUE (tree))
1751 if (IS_AST_SYM_VALUE (tree))
1752 return isSymbolEqual (AST_SYMBOL (tree), sym);
1757 return astHasSymbol (tree->left, sym) ||
1758 astHasSymbol (tree->right, sym);
1761 /*-----------------------------------------------------------------*/
1762 /* astHasDeref - return true if the ast has an indirect access */
1763 /*-----------------------------------------------------------------*/
1765 astHasDeref (ast * tree)
1767 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE(tree))
1770 if (tree->opval.op == '*' && tree->right == NULL) return TRUE;
1772 return astHasDeref (tree->left) || astHasDeref (tree->right);
1775 /*-----------------------------------------------------------------*/
1776 /* isConformingBody - the loop body has to conform to a set of rules */
1777 /* for the loop to be considered reversible read on for rules */
1778 /*-----------------------------------------------------------------*/
1780 isConformingBody (ast * pbody, symbol * sym, ast * body)
1783 /* we are going to do a pre-order traversal of the
1784 tree && check for the following conditions. (essentially
1785 a set of very shallow tests )
1786 a) the sym passed does not participate in
1787 any arithmetic operation
1788 b) There are no function calls
1789 c) all jumps are within the body
1790 d) address of loop control variable not taken
1791 e) if an assignment has a pointer on the
1792 left hand side make sure right does not have
1793 loop control variable */
1795 /* if we reach the end or a leaf then true */
1796 if (!pbody || IS_AST_LINK (pbody) || IS_AST_VALUE (pbody))
1799 /* if anything else is "volatile" */
1800 if (IS_VOLATILE (TETYPE (pbody)))
1803 /* we will walk the body in a pre-order traversal for
1805 switch (pbody->opval.op)
1807 /*------------------------------------------------------------------*/
1809 // if the loopvar is used as an index
1810 /* array op is commutative -- must check both left & right */
1811 if (astHasSymbol(pbody->right, sym) || astHasSymbol(pbody->left, sym)) {
1814 return isConformingBody (pbody->right, sym, body)
1815 && isConformingBody (pbody->left, sym, body);
1817 /*------------------------------------------------------------------*/
1822 /*------------------------------------------------------------------*/
1826 /* sure we are not sym is not modified */
1828 IS_AST_SYM_VALUE (pbody->left) &&
1829 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1833 IS_AST_SYM_VALUE (pbody->right) &&
1834 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1839 /*------------------------------------------------------------------*/
1841 case '*': /* can be unary : if right is null then unary operation */
1846 /* if right is NULL then unary operation */
1847 /*------------------------------------------------------------------*/
1848 /*----------------------------*/
1850 /*----------------------------*/
1853 if (IS_AST_SYM_VALUE (pbody->left) &&
1854 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1857 return isConformingBody (pbody->left, sym, body);
1861 if (astHasSymbol (pbody->left, sym) ||
1862 astHasSymbol (pbody->right, sym))
1867 /*------------------------------------------------------------------*/
1878 if (IS_AST_SYM_VALUE (pbody->left) &&
1879 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1882 if (IS_AST_SYM_VALUE (pbody->right) &&
1883 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1886 return isConformingBody (pbody->left, sym, body) &&
1887 isConformingBody (pbody->right, sym, body);
1895 if (IS_AST_SYM_VALUE (pbody->left) &&
1896 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1898 return isConformingBody (pbody->left, sym, body);
1900 /*------------------------------------------------------------------*/
1912 case SIZEOF: /* evaluate wihout code generation */
1914 if (IS_AST_SYM_VALUE (pbody->left) &&
1915 isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1918 if (IS_AST_SYM_VALUE (pbody->right) &&
1919 isSymbolEqual (AST_SYMBOL (pbody->right), sym))
1922 return isConformingBody (pbody->left, sym, body) &&
1923 isConformingBody (pbody->right, sym, body);
1925 /*------------------------------------------------------------------*/
1928 /* if left has a pointer & right has loop
1929 control variable then we cannot */
1930 if (astHasPointer (pbody->left) &&
1931 astHasSymbol (pbody->right, sym))
1933 if (astHasVolatile (pbody->left))
1936 if (IS_AST_SYM_VALUE (pbody->left)) {
1937 // if the loopvar has an assignment
1938 if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
1940 // if the loopvar is used in another (maybe conditional) block
1941 if (astHasSymbol (pbody->right, sym) &&
1942 (pbody->level >= body->level)) {
1947 if (astHasVolatile (pbody->left))
1950 if (astHasDeref(pbody->right)) return FALSE;
1952 return isConformingBody (pbody->left, sym, body) &&
1953 isConformingBody (pbody->right, sym, body);
1964 assert ("Parser should not have generated this\n");
1966 /*------------------------------------------------------------------*/
1967 /*----------------------------*/
1968 /* comma operator */
1969 /*----------------------------*/
1971 return isConformingBody (pbody->left, sym, body) &&
1972 isConformingBody (pbody->right, sym, body);
1974 /*------------------------------------------------------------------*/
1975 /*----------------------------*/
1977 /*----------------------------*/
1979 /* if local & not passed as paramater then ok */
1980 if (sym->level && !astHasSymbol(pbody->right,sym))
1984 /*------------------------------------------------------------------*/
1985 /*----------------------------*/
1986 /* return statement */
1987 /*----------------------------*/
1992 if (isLabelInAst (AST_SYMBOL (pbody->left), body))
1997 if (astHasSymbol (pbody->left, sym))
2004 return isConformingBody (pbody->left, sym, body) &&
2005 isConformingBody (pbody->right, sym, body);
2011 /*-----------------------------------------------------------------*/
2012 /* isLoopReversible - takes a for loop as input && returns true */
2013 /* if the for loop is reversible. If yes will set the value of */
2014 /* the loop control var & init value & termination value */
2015 /*-----------------------------------------------------------------*/
2017 isLoopReversible (ast * loop, symbol ** loopCntrl,
2018 ast ** init, ast ** end)
2020 /* if option says don't do it then don't */
2021 if (optimize.noLoopReverse)
2023 /* there are several tests to determine this */
2025 /* for loop has to be of the form
2026 for ( <sym> = <const1> ;
2027 [<sym> < <const2>] ;
2028 [<sym>++] | [<sym> += 1] | [<sym> = <sym> + 1] )
2030 if (!isLoopCountable (AST_FOR (loop, initExpr),
2031 AST_FOR (loop, condExpr),
2032 AST_FOR (loop, loopExpr),
2033 loopCntrl, init, end))
2036 /* now do some serious checking on the body of the loop
2039 return isConformingBody (loop->left, *loopCntrl, loop->left);
2043 /*-----------------------------------------------------------------*/
2044 /* replLoopSym - replace the loop sym by loop sym -1 */
2045 /*-----------------------------------------------------------------*/
2047 replLoopSym (ast * body, symbol * sym)
2050 if (!body || IS_AST_LINK (body))
2053 if (IS_AST_SYM_VALUE (body))
2056 if (isSymbolEqual (AST_SYMBOL (body), sym))
2060 body->opval.op = '-';
2061 body->left = newAst_VALUE (symbolVal (sym));
2062 body->right = newAst_VALUE (constVal ("1"));
2070 replLoopSym (body->left, sym);
2071 replLoopSym (body->right, sym);
2075 /*-----------------------------------------------------------------*/
2076 /* reverseLoop - do the actual loop reversal */
2077 /*-----------------------------------------------------------------*/
2079 reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
2083 /* create the following tree
2088 if (sym) goto for_continue ;
2091 /* put it together piece by piece */
2092 rloop = newNode (NULLOP,
2093 createIf (newAst_VALUE (symbolVal (sym)),
2095 newAst_VALUE (symbolVal (AST_FOR (loop, continueLabel))),
2098 newAst_VALUE (symbolVal (sym)),
2101 replLoopSym (loop->left, sym);
2102 setAstLineno (rloop, init->lineno);
2104 rloop = newNode (NULLOP,
2106 newAst_VALUE (symbolVal (sym)),
2107 newNode ('-', end, init)),
2108 createLabel (AST_FOR (loop, continueLabel),
2112 newNode (SUB_ASSIGN,
2113 newAst_VALUE (symbolVal (sym)),
2114 newAst_VALUE (constVal ("1"))),
2117 rloop->lineno=init->lineno;
2118 return decorateType (rloop, RESULT_TYPE_NONE);
2122 /*-----------------------------------------------------------------*/
2123 /* searchLitOp - search tree (*ops only) for an ast with literal */
2124 /*-----------------------------------------------------------------*/
2126 searchLitOp (ast *tree, ast **parent, const char *ops)
2130 if (tree && optimize.global_cse)
2132 /* is there a literal operand? */
2134 IS_AST_OP(tree->right) &&
2135 tree->right->right &&
2136 (tree->right->opval.op == (unsigned)ops[0] || tree->right->opval.op == (unsigned)ops[1]))
2138 if (IS_LITERAL (RTYPE (tree->right)) !=
2139 IS_LITERAL (LTYPE (tree->right)))
2141 tree->right->decorated = 0;
2142 tree->decorated = 0;
2146 ret = searchLitOp (tree->right, parent, ops);
2151 IS_AST_OP(tree->left) &&
2152 tree->left->right &&
2153 (tree->left->opval.op == (unsigned)ops[0] || tree->left->opval.op == (unsigned)ops[1]))
2155 if (IS_LITERAL (RTYPE (tree->left)) !=
2156 IS_LITERAL (LTYPE (tree->left)))
2158 tree->left->decorated = 0;
2159 tree->decorated = 0;
2163 ret = searchLitOp (tree->left, parent, ops);
2171 /*-----------------------------------------------------------------*/
2172 /* getResultFromType */
2173 /*-----------------------------------------------------------------*/
2175 getResultTypeFromType (sym_link *type)
2177 /* type = getSpec (type); */
2179 return RESULT_TYPE_BIT;
2180 if (IS_BITFIELD (type))
2182 int blen = SPEC_BLEN (type);
2185 return RESULT_TYPE_BIT;
2187 return RESULT_TYPE_CHAR;
2188 return RESULT_TYPE_INT;
2191 return RESULT_TYPE_CHAR;
2192 if (IS_INT (type) && !IS_LONG (type))
2193 return RESULT_TYPE_INT;
2194 return RESULT_TYPE_OTHER;
2197 /*-----------------------------------------------------------------*/
2198 /* addCast - adds casts to a type specified by RESULT_TYPE */
2199 /*-----------------------------------------------------------------*/
2201 addCast (ast *tree, RESULT_TYPE resultType, bool promote)
2204 bool upCasted = FALSE;
2208 case RESULT_TYPE_NONE:
2209 /* if thing smaller than int must be promoted to int */
2211 getSize (tree->etype) >= INTSIZE)
2212 /* promotion not necessary or already an int */
2214 /* char and bits: promote to int */
2215 newLink = newIntLink();
2218 case RESULT_TYPE_BIT:
2220 /* already an int */
2221 bitsForType (tree->etype) >= 16 ||
2222 /* bit to bit operation: don't promote, the code generators
2223 hopefully know everything about promotion rules */
2224 bitsForType (tree->etype) == 1)
2226 newLink = newIntLink();
2229 case RESULT_TYPE_CHAR:
2230 if (IS_CHAR (tree->etype) ||
2231 IS_FLOAT(tree->etype) ||
2232 IS_FIXED(tree->etype))
2234 newLink = newCharLink();
2236 case RESULT_TYPE_INT:
2238 if (getSize (tree->etype) > INTSIZE)
2240 /* warn ("Loosing significant digits"); */
2244 /* char: promote to int */
2246 getSize (tree->etype) >= INTSIZE)
2248 newLink = newIntLink();
2251 case RESULT_TYPE_IFX:
2252 case RESULT_TYPE_OTHER:
2254 /* return type is ifx, long, float: promote char to int */
2255 getSize (tree->etype) >= INTSIZE)
2257 newLink = newIntLink();
2263 tree->decorated = 0;
2264 tree = newNode (CAST, newAst_LINK (newLink), tree);
2265 tree->lineno = tree->right->lineno;
2266 /* keep unsigned type during cast to smaller type,
2267 but not when promoting from char to int */
2269 SPEC_USIGN (tree->left->opval.lnk) = IS_UNSIGNED (tree->right->etype) ? 1 : 0;
2270 return decorateType (tree, resultType);
2273 /*-----------------------------------------------------------------*/
2274 /* resultTypePropagate - decides if resultType can be propagated */
2275 /*-----------------------------------------------------------------*/
2277 resultTypePropagate (ast *tree, RESULT_TYPE resultType)
2279 switch (tree->opval.op)
2299 return RESULT_TYPE_NONE;
2303 return RESULT_TYPE_IFX;
2305 return RESULT_TYPE_NONE;
2309 /*-----------------------------------------------------------------*/
2310 /* getLeftResultType - gets type from left branch for propagation */
2311 /*-----------------------------------------------------------------*/
2313 getLeftResultType (ast *tree, RESULT_TYPE resultType)
2315 switch (tree->opval.op)
2319 if (IS_PTR (LTYPE (tree)))
2320 return RESULT_TYPE_NONE;
2322 return getResultTypeFromType (LETYPE (tree));
2324 if (IS_PTR (currFunc->type->next))
2325 return RESULT_TYPE_NONE;
2327 return getResultTypeFromType (currFunc->type->next);
2329 if (!IS_ARRAY (LTYPE (tree)))
2331 if (DCL_ELEM (LTYPE (tree)) > 0 && DCL_ELEM (LTYPE (tree)) <= 255)
2332 return RESULT_TYPE_CHAR;
2339 /*------------------------------------------------------------------*/
2340 /* gatherImplicitVariables: assigns correct type information to */
2341 /* symbols and values created by replaceAstWithTemporary */
2342 /* and adds the symbols to the declarations list of the */
2343 /* innermost block that contains them */
2344 /*------------------------------------------------------------------*/
2346 gatherImplicitVariables (ast * tree, ast * block)
2351 if (tree->type == EX_OP && tree->opval.op == BLOCK)
2353 /* keep track of containing scope */
2356 if (tree->type == EX_OP && tree->opval.op == '=' &&
2357 tree->left->type == EX_VALUE && tree->left->opval.val->sym)
2359 symbol *assignee = tree->left->opval.val->sym;
2361 /* special case for assignment to compiler-generated temporary variable:
2362 compute type of RHS, and set the symbol's type to match */
2363 if (assignee->type == NULL && assignee->infertype) {
2364 ast *dtr = decorateType (resolveSymbols(tree->right), RESULT_TYPE_NONE);
2366 if (dtr != tree->right)
2369 assignee->type = copyLinkChain(TTYPE(dtr));
2370 assignee->etype = getSpec(assignee->type);
2371 SPEC_SCLS (assignee->etype) = S_AUTO;
2372 SPEC_OCLS (assignee->etype) = NULL;
2373 SPEC_EXTR (assignee->etype) = 0;
2374 SPEC_STAT (assignee->etype) = 0;
2375 SPEC_VOLATILE (assignee->etype) = 0;
2376 SPEC_ABSA (assignee->etype) = 0;
2378 wassertl(block != NULL, "implicit variable not contained in block");
2379 wassert(assignee->next == NULL);
2380 if (block != NULL) {
2381 symbol **decl = &(block->values.sym);
2384 wassert(*decl != assignee); /* should not already be in list */
2385 decl = &( (*decl)->next );
2392 if (tree->type == EX_VALUE && !(IS_LITERAL(tree->opval.val->etype)) &&
2393 tree->opval.val->type == NULL &&
2394 tree->opval.val->sym &&
2395 tree->opval.val->sym->infertype)
2397 /* fixup type of value for compiler-inferred temporary var */
2398 tree->opval.val->type = tree->opval.val->sym->type;
2399 tree->opval.val->etype = tree->opval.val->sym->etype;
2402 gatherImplicitVariables(tree->left, block);
2403 gatherImplicitVariables(tree->right, block);
2406 /*--------------------------------------------------------------------*/
2407 /* decorateType - compute type for this tree, also does type checking.*/
2408 /* This is done bottom up, since type has to flow upwards. */
2409 /* resultType flows top-down and forces e.g. char-arithmetic, if the */
2410 /* result is a char and the operand(s) are int's. */
2411 /* It also does constant folding, and parameter checking. */
2412 /*--------------------------------------------------------------------*/
2414 decorateType (ast * tree, RESULT_TYPE resultType)
2418 RESULT_TYPE resultTypeProp;
2423 /* if already has type then do nothing */
2424 if (tree->decorated)
2427 tree->decorated = 1;
2430 /* print the line */
2431 /* if not block & function */
2432 if (tree->type == EX_OP &&
2433 (tree->opval.op != FUNCTION &&
2434 tree->opval.op != BLOCK &&
2435 tree->opval.op != NULLOP))
2437 filename = tree->filename;
2438 lineno = tree->lineno;
2442 /* if any child is an error | this one is an error do nothing */
2443 if (tree->isError ||
2444 (tree->left && tree->left->isError) ||
2445 (tree->right && tree->right->isError))
2448 /*------------------------------------------------------------------*/
2449 /*----------------------------*/
2450 /* leaf has been reached */
2451 /*----------------------------*/
2452 lineno = tree->lineno;
2453 /* if this is of type value */
2454 /* just get the type */
2455 if (tree->type == EX_VALUE)
2458 if (IS_LITERAL (tree->opval.val->etype))
2461 /* if this is a character array then declare it */
2462 if (IS_ARRAY (tree->opval.val->type))
2463 tree->opval.val = stringToSymbol (tree->opval.val);
2465 /* otherwise just copy the type information */
2466 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2470 if (tree->opval.val->sym)
2472 /* if the undefined flag is set then give error message */
2473 if (tree->opval.val->sym->undefined)
2475 werrorfl (tree->filename, tree->lineno, E_ID_UNDEF, tree->opval.val->sym->name);
2477 TTYPE (tree) = TETYPE (tree) =
2478 tree->opval.val->type = tree->opval.val->sym->type =
2479 tree->opval.val->etype = tree->opval.val->sym->etype =
2480 copyLinkChain (INTTYPE);
2482 else if (tree->opval.val->sym->implicit)
2484 /* if implicit i.e. struct/union member then no type */
2485 TTYPE (tree) = TETYPE (tree) = NULL;
2489 /* copy the type from the value into the ast */
2490 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.val->type);
2492 /* and mark the symbol as referenced */
2493 tree->opval.val->sym->isref = 1;
2497 wassert(0); /* unreached: all values are literals or symbols */
2502 /* if type link for the case of cast */
2503 if (tree->type == EX_LINK)
2505 COPYTYPE (TTYPE (tree), TETYPE (tree), tree->opval.lnk);
2513 if (tree->opval.op == NULLOP || tree->opval.op == BLOCK)
2515 if (tree->left && tree->left->type == EX_OPERAND
2516 && (tree->left->opval.op == INC_OP
2517 || tree->left->opval.op == DEC_OP)
2518 && tree->left->left)
2520 tree->left->right = tree->left->left;
2521 tree->left->left = NULL;
2523 if (tree->right && tree->right->type == EX_OPERAND
2524 && (tree->right->opval.op == INC_OP
2525 || tree->right->opval.op == DEC_OP)
2526 && tree->right->left)
2528 tree->right->right = tree->right->left;
2529 tree->right->left = NULL;
2534 /* Before decorating the left branch we've to decide in dependence
2535 upon tree->opval.op, if resultType can be propagated */
2536 resultTypeProp = resultTypePropagate (tree, resultType);
2538 if ((tree->opval.op == '?') && (resultTypeProp != RESULT_TYPE_BIT))
2539 dtl = decorateType (tree->left, RESULT_TYPE_IFX);
2541 dtl = decorateType (tree->left, resultTypeProp);
2543 /* if an array node, we may need to swap branches */
2544 if (tree->opval.op == '[')
2546 /* determine which is the array & which the index */
2547 if ((IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))) &&
2548 IS_INTEGRAL (LTYPE (tree)))
2550 ast *tempTree = tree->left;
2551 tree->left = tree->right;
2552 tree->right = tempTree;
2556 /* After decorating the left branch there's type information available
2557 in tree->left->?type. If the op is e.g. '=' we extract the type
2558 information from there and propagate it to the right branch. */
2559 resultTypeProp = getLeftResultType (tree, resultTypeProp);
2561 switch (tree->opval.op)
2564 /* delay right side for '?' operator since conditional macro
2565 expansions might rely on this */
2569 /* decorate right side for CALL (parameter list) in processParms();
2570 there is resultType available */
2574 /* don't allocate string if it is a sizeof argument */
2576 dtr = decorateType (tree->right, resultTypeProp);
2580 dtr = decorateType (tree->right, resultTypeProp);
2584 /* this is to take care of situations
2585 when the tree gets rewritten */
2586 if (dtl != tree->left)
2588 if (dtr != tree->right)
2590 if ((dtl && dtl->isError) || (dtr && dtr->isError))
2594 /* depending on type of operator do */
2596 switch (tree->opval.op)
2598 /*------------------------------------------------------------------*/
2599 /*----------------------------*/
2601 /*----------------------------*/
2604 /* first check if this is a array or a pointer */
2605 if ((!IS_ARRAY (LTYPE (tree))) && (!IS_PTR (LTYPE (tree))))
2607 werrorfl (tree->filename, tree->lineno, E_NEED_ARRAY_PTR, "[]");
2608 goto errorTreeReturn;
2611 /* check if the type of the idx */
2612 if (!IS_INTEGRAL (RTYPE (tree)))
2614 werrorfl (tree->filename, tree->lineno, E_IDX_NOT_INT);
2615 goto errorTreeReturn;
2618 /* if the left is an rvalue then error */
2621 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "array access");
2622 goto errorTreeReturn;
2625 if (IS_LITERAL (RTYPE (tree)))
2627 int arrayIndex = (int) ulFromVal (valFromType (RETYPE (tree)));
2628 int arraySize = DCL_ELEM (LTYPE (tree));
2629 if (arraySize && arrayIndex >= arraySize)
2631 werrorfl (tree->filename, tree->lineno, W_IDX_OUT_OF_BOUNDS, arrayIndex, arraySize);
2636 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
2637 SPEC_CONST (TETYPE (tree)) |= DCL_PTR_CONST (LTYPE (tree));
2640 /*------------------------------------------------------------------*/
2641 /*----------------------------*/
2643 /*----------------------------*/
2645 /* if this is not a structure */
2646 if (!IS_STRUCT (LTYPE (tree)))
2648 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, ".");
2649 goto errorTreeReturn;
2651 TTYPE (tree) = structElemType (LTYPE (tree),
2652 (tree->right->type == EX_VALUE ?
2653 tree->right->opval.val : NULL));
2654 TETYPE (tree) = getSpec (TTYPE (tree));
2657 /*------------------------------------------------------------------*/
2658 /*----------------------------*/
2659 /* struct/union pointer */
2660 /*----------------------------*/
2662 /* if not pointer to a structure */
2663 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE(tree)))
2665 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
2666 goto errorTreeReturn;
2669 if (!IS_STRUCT (LTYPE (tree)->next))
2671 werrorfl (tree->filename, tree->lineno, E_STRUCT_UNION, "->");
2672 goto errorTreeReturn;
2675 TTYPE (tree) = structElemType (LTYPE (tree)->next,
2676 (tree->right->type == EX_VALUE ?
2677 tree->right->opval.val : NULL));
2678 TETYPE (tree) = getSpec (TTYPE (tree));
2680 /* adjust the storage class */
2681 switch (DCL_TYPE(tree->left->ftype)) {
2683 SPEC_SCLS(TETYPE(tree)) = S_DATA;
2686 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
2689 SPEC_SCLS(TETYPE(tree)) = S_CODE;
2692 SPEC_SCLS (TETYPE (tree)) = 0;
2695 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
2698 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
2701 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
2704 SPEC_SCLS (TETYPE (tree)) = 0;
2711 /* This breaks with extern declarations, bitfields, and perhaps other */
2712 /* cases (gcse). Let's leave this optimization disabled for now and */
2713 /* ponder if there's a safe way to do this. -- EEP */
2715 if (IS_ADDRESS_OF_OP (tree->left) && IS_AST_SYM_VALUE(tree->left->left)
2716 && SPEC_ABSA (AST_SYMBOL (tree->left->left)->etype))
2718 /* If defined struct type at addr var
2719 then rewrite (&struct var)->member
2721 and define membertype at (addr+offsetof(struct var,member)) temp
2724 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree)),
2725 AST_SYMBOL(tree->right));
2727 sym = newSymbol(genSymName (0), 0);
2728 sym->type = TTYPE (tree);
2729 sym->etype = getSpec(sym->type);
2730 sym->lineDef = tree->lineno;
2733 SPEC_STAT (sym->etype) = 1;
2734 SPEC_ADDR (sym->etype) = SPEC_ADDR (AST_SYMBOL (tree->left->left)->etype)
2736 SPEC_ABSA(sym->etype) = 1;
2737 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
2740 AST_VALUE (tree) = symbolVal(sym);
2743 tree->type = EX_VALUE;
2751 /*------------------------------------------------------------------*/
2752 /*----------------------------*/
2753 /* ++/-- operation */
2754 /*----------------------------*/
2758 sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
2759 COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
2760 if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
2761 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
2770 /*------------------------------------------------------------------*/
2771 /*----------------------------*/
2773 /*----------------------------*/
2774 case '&': /* can be unary */
2775 /* if right is NULL then unary operation */
2776 if (tree->right) /* not an unary operation */
2779 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
2781 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
2782 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
2783 printTypeChain (LTYPE (tree), stderr);
2784 fprintf (stderr, ",");
2785 printTypeChain (RTYPE (tree), stderr);
2786 fprintf (stderr, "\n");
2787 goto errorTreeReturn;
2790 /* if they are both literal */
2791 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
2793 tree->type = EX_VALUE;
2794 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
2795 valFromType (RETYPE (tree)), '&');
2797 tree->right = tree->left = NULL;
2798 TETYPE (tree) = tree->opval.val->etype;
2799 TTYPE (tree) = tree->opval.val->type;
2803 /* see if this is a GETHBIT operation if yes
2806 ast *otree = optimizeGetHbit (tree, resultType);
2809 return decorateType (otree, RESULT_TYPE_NONE);
2812 /* see if this is a GETABIT operation if yes
2815 ast *otree = optimizeGetAbit (tree, resultType);
2818 return decorateType (otree, RESULT_TYPE_NONE);
2821 /* see if this is a GETBYTE operation if yes
2824 ast *otree = optimizeGetByte (tree, resultType);
2827 return decorateType (otree, RESULT_TYPE_NONE);
2830 /* see if this is a GETWORD operation if yes
2833 ast *otree = optimizeGetWord (tree, resultType);
2836 return decorateType (otree, RESULT_TYPE_NONE);
2839 /* if left is a literal exchange left & right */
2840 if (IS_LITERAL (LTYPE (tree)))
2842 ast *tTree = tree->left;
2843 tree->left = tree->right;
2844 tree->right = tTree;
2847 /* if right is a literal and */
2848 /* we can find a 2nd literal in an and-tree then */
2849 /* rearrange the tree */
2850 if (IS_LITERAL (RTYPE (tree)))
2853 ast *litTree = searchLitOp (tree, &parent, "&");
2857 ast *tTree = litTree->left;
2858 litTree->left = tree->right;
2859 tree->right = tTree;
2860 /* both operands in litTree are literal now */
2861 decorateType (parent, resultType);
2865 LRVAL (tree) = RRVAL (tree) = 1;
2867 TTYPE (tree) = computeType (LTYPE (tree),
2871 TETYPE (tree) = getSpec (TTYPE (tree));
2876 /*------------------------------------------------------------------*/
2877 /*----------------------------*/
2879 /*----------------------------*/
2880 p = newLink (DECLARATOR);
2881 /* if bit field then error */
2882 if (IS_BITVAR (tree->left->etype))
2884 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of bit variable");
2885 goto errorTreeReturn;
2888 if (LETYPE(tree) && SPEC_SCLS (tree->left->etype) == S_REGISTER)
2890 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of register variable");
2891 goto errorTreeReturn;
2894 if (IS_FUNC (LTYPE (tree)))
2896 // this ought to be ignored
2897 return (tree->left);
2900 if (IS_LITERAL(LTYPE(tree)))
2902 werrorfl (tree->filename, tree->lineno, E_ILLEGAL_ADDR, "address of literal");
2903 goto errorTreeReturn;
2908 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "address of");
2909 goto errorTreeReturn;
2912 DCL_TYPE (p) = POINTER;
2913 else if (SPEC_SCLS (tree->left->etype) == S_CODE)
2914 DCL_TYPE (p) = CPOINTER;
2915 else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
2916 DCL_TYPE (p) = FPOINTER;
2917 else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
2918 DCL_TYPE (p) = PPOINTER;
2919 else if (SPEC_SCLS (tree->left->etype) == S_IDATA)
2920 DCL_TYPE (p) = IPOINTER;
2921 else if (SPEC_SCLS (tree->left->etype) == S_EEPROM)
2922 DCL_TYPE (p) = EEPPOINTER;
2923 else if (SPEC_OCLS(tree->left->etype))
2924 DCL_TYPE (p) = PTR_TYPE(SPEC_OCLS(tree->left->etype));
2926 DCL_TYPE (p) = POINTER;
2928 if (IS_AST_SYM_VALUE (tree->left))
2930 AST_SYMBOL (tree->left)->addrtaken = 1;
2931 AST_SYMBOL (tree->left)->allocreq = 1;
2934 p->next = LTYPE (tree);
2936 TETYPE (tree) = getSpec (TTYPE (tree));
2941 if (IS_AST_OP (tree->left) && tree->left->opval.op == PTR_OP
2942 && IS_AST_VALUE (tree->left->left) && !IS_AST_SYM_VALUE (tree->left->left))
2944 symbol *element = getStructElement (SPEC_STRUCT (LETYPE(tree->left)),
2945 AST_SYMBOL(tree->left->right));
2946 AST_VALUE(tree) = valPlus(AST_VALUE(tree->left->left),
2947 valueFromLit(element->offset));
2950 tree->type = EX_VALUE;
2951 tree->values.literalFromCast = 1;
2957 /*------------------------------------------------------------------*/
2958 /*----------------------------*/
2960 /*----------------------------*/
2962 /* if the rewrite succeeds then don't go any further */
2964 ast *wtree = optimizeRRCRLC (tree);
2966 return decorateType (wtree, RESULT_TYPE_NONE);
2968 wtree = optimizeSWAP (tree);
2970 return decorateType (wtree, RESULT_TYPE_NONE);
2973 /* if left is a literal exchange left & right */
2974 if (IS_LITERAL (LTYPE (tree)))
2976 ast *tTree = tree->left;
2977 tree->left = tree->right;
2978 tree->right = tTree;
2981 /* if right is a literal and */
2982 /* we can find a 2nd literal in an or-tree then */
2983 /* rearrange the tree */
2984 if (IS_LITERAL (RTYPE (tree)))
2987 ast *litTree = searchLitOp (tree, &parent, "|");
2991 ast *tTree = litTree->left;
2992 litTree->left = tree->right;
2993 tree->right = tTree;
2994 /* both operands in tTree are literal now */
2995 decorateType (parent, resultType);
3000 /*------------------------------------------------------------------*/
3001 /*----------------------------*/
3003 /*----------------------------*/
3005 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3007 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3008 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3009 printTypeChain (LTYPE (tree), stderr);
3010 fprintf (stderr, ",");
3011 printTypeChain (RTYPE (tree), stderr);
3012 fprintf (stderr, "\n");
3013 goto errorTreeReturn;
3016 /* if they are both literal then rewrite the tree */
3017 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3019 tree->type = EX_VALUE;
3020 tree->opval.val = valBitwise (valFromType (LETYPE (tree)),
3021 valFromType (RETYPE (tree)),
3023 tree->right = tree->left = NULL;
3024 TETYPE (tree) = tree->opval.val->etype;
3025 TTYPE (tree) = tree->opval.val->type;
3029 /* if left is a literal exchange left & right */
3030 if (IS_LITERAL (LTYPE (tree)))
3032 ast *tTree = tree->left;
3033 tree->left = tree->right;
3034 tree->right = tTree;
3037 /* if right is a literal and */
3038 /* we can find a 2nd literal in a xor-tree then */
3039 /* rearrange the tree */
3040 if (IS_LITERAL (RTYPE (tree)) &&
3041 tree->opval.op == '^') /* the same source is used by 'bitwise or' */
3044 ast *litTree = searchLitOp (tree, &parent, "^");
3048 ast *tTree = litTree->left;
3049 litTree->left = tree->right;
3050 tree->right = tTree;
3051 /* both operands in litTree are literal now */
3052 decorateType (parent, resultType);
3056 LRVAL (tree) = RRVAL (tree) = 1;
3058 TTYPE (tree) = computeType (LTYPE (tree),
3062 TETYPE (tree) = getSpec (TTYPE (tree));
3066 /*------------------------------------------------------------------*/
3067 /*----------------------------*/
3069 /*----------------------------*/
3071 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3073 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "divide");
3074 goto errorTreeReturn;
3076 /* if they are both literal then */
3077 /* rewrite the tree */
3078 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3080 tree->type = EX_VALUE;
3081 tree->opval.val = valDiv (valFromType (LETYPE (tree)),
3082 valFromType (RETYPE (tree)));
3083 tree->right = tree->left = NULL;
3084 TETYPE (tree) = getSpec (TTYPE (tree) =
3085 tree->opval.val->type);
3089 LRVAL (tree) = RRVAL (tree) = 1;
3091 TETYPE (tree) = getSpec (TTYPE (tree) =
3092 computeType (LTYPE (tree),
3097 /* if right is a literal and */
3098 /* left is also a division by a literal then */
3099 /* rearrange the tree */
3100 if (IS_LITERAL (RTYPE (tree))
3101 /* avoid infinite loop */
3102 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 1)
3105 ast *litTree = searchLitOp (tree, &parent, "/");
3108 if (IS_LITERAL (RTYPE (litTree)))
3112 litTree->right = newNode ('*',
3114 copyAst (tree->right));
3115 litTree->right->lineno = tree->lineno;
3117 tree->right->opval.val = constVal ("1");
3118 decorateType (parent, resultType);
3122 /* litTree->left is literal: no gcse possible.
3123 We can't call decorateType(parent, RESULT_TYPE_NONE), because
3124 this would cause an infinit loop. */
3125 parent->decorated = 1;
3126 decorateType (litTree, resultType);
3133 /*------------------------------------------------------------------*/
3134 /*----------------------------*/
3136 /*----------------------------*/
3138 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (RTYPE (tree)))
3140 werrorfl (tree->filename, tree->lineno, E_BITWISE_OP);
3141 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3142 printTypeChain (LTYPE (tree), stderr);
3143 fprintf (stderr, ",");
3144 printTypeChain (RTYPE (tree), stderr);
3145 fprintf (stderr, "\n");
3146 goto errorTreeReturn;
3148 /* if they are both literal then */
3149 /* rewrite the tree */
3150 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3152 tree->type = EX_VALUE;
3153 tree->opval.val = valMod (valFromType (LETYPE (tree)),
3154 valFromType (RETYPE (tree)));
3155 tree->right = tree->left = NULL;
3156 TETYPE (tree) = getSpec (TTYPE (tree) =
3157 tree->opval.val->type);
3160 LRVAL (tree) = RRVAL (tree) = 1;
3161 TETYPE (tree) = getSpec (TTYPE (tree) =
3162 computeType (LTYPE (tree),
3168 /*------------------------------------------------------------------*/
3169 /*----------------------------*/
3170 /* address dereference */
3171 /*----------------------------*/
3172 case '*': /* can be unary : if right is null then unary operation */
3175 if (!IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3177 werrorfl (tree->filename, tree->lineno, E_PTR_REQD);
3178 goto errorTreeReturn;
3183 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "pointer deref");
3184 goto errorTreeReturn;
3186 if (IS_ADDRESS_OF_OP(tree->left))
3188 /* replace *&obj with obj */
3189 return tree->left->left;
3191 TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
3192 TETYPE (tree) = getSpec (TTYPE (tree));
3193 /* adjust the storage class */
3194 switch (DCL_TYPE(tree->left->ftype)) {
3196 SPEC_SCLS(TETYPE(tree)) = S_DATA;
3199 SPEC_SCLS(TETYPE(tree)) = S_XDATA;
3202 SPEC_SCLS(TETYPE(tree)) = S_CODE;
3205 SPEC_SCLS (TETYPE (tree)) = 0;
3208 SPEC_SCLS(TETYPE(tree)) = S_XSTACK;
3211 SPEC_SCLS(TETYPE(tree)) = S_IDATA;
3214 SPEC_SCLS(TETYPE(tree)) = S_EEPROM;
3217 SPEC_SCLS (TETYPE (tree)) = 0;
3226 /*------------------------------------------------------------------*/
3227 /*----------------------------*/
3228 /* multiplication */
3229 /*----------------------------*/
3230 if (!IS_ARITHMETIC (LTYPE (tree)) || !IS_ARITHMETIC (RTYPE (tree)))
3232 werrorfl (tree->filename, tree->lineno, E_INVALID_OP, "multiplication");
3233 goto errorTreeReturn;
3236 /* if they are both literal then */
3237 /* rewrite the tree */
3238 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3240 tree->type = EX_VALUE;
3241 tree->opval.val = valMult (valFromType (LETYPE (tree)),
3242 valFromType (RETYPE (tree)));
3243 tree->right = tree->left = NULL;
3244 TETYPE (tree) = getSpec (TTYPE (tree) =
3245 tree->opval.val->type);
3249 /* if left is a literal exchange left & right */
3250 if (IS_LITERAL (LTYPE (tree)))
3252 ast *tTree = tree->left;
3253 tree->left = tree->right;
3254 tree->right = tTree;
3257 /* if right is a literal and */
3258 /* we can find a 2nd literal in a mul-tree then */
3259 /* rearrange the tree */
3260 if (IS_LITERAL (RTYPE (tree)))
3263 ast *litTree = searchLitOp (tree, &parent, "*");
3267 ast *tTree = litTree->left;
3268 litTree->left = tree->right;
3269 tree->right = tTree;
3270 /* both operands in litTree are literal now */
3271 decorateType (parent, resultType);
3275 LRVAL (tree) = RRVAL (tree) = 1;
3276 tree->left = addCast (tree->left, resultType, FALSE);
3277 tree->right = addCast (tree->right, resultType, FALSE);
3278 TETYPE (tree) = getSpec (TTYPE (tree) =
3279 computeType (LTYPE (tree),
3286 /*------------------------------------------------------------------*/
3287 /*----------------------------*/
3288 /* unary '+' operator */
3289 /*----------------------------*/
3294 if (!IS_ARITHMETIC (LTYPE (tree)))
3296 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, '+');
3297 goto errorTreeReturn;
3300 /* if left is a literal then do it */
3301 if (IS_LITERAL (LTYPE (tree)))
3303 tree->type = EX_VALUE;
3304 tree->opval.val = valFromType (LETYPE (tree));
3306 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3310 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3314 /*------------------------------------------------------------------*/
3315 /*----------------------------*/
3317 /*----------------------------*/
3319 /* this is not a unary operation */
3320 /* if both pointers then problem */
3321 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3322 (IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree))))
3324 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
3325 goto errorTreeReturn;
3328 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3329 !IS_PTR (LTYPE (tree)) && !IS_ARRAY (LTYPE (tree)))
3331 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3332 goto errorTreeReturn;
3335 if (!IS_ARITHMETIC (RTYPE (tree)) &&
3336 !IS_PTR (RTYPE (tree)) && !IS_ARRAY (RTYPE (tree)))
3338 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+");
3339 goto errorTreeReturn;
3341 /* if they are both literal then */
3342 /* rewrite the tree */
3343 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3345 tree->type = EX_VALUE;
3346 tree->left = addCast (tree->left, resultType, TRUE);
3347 tree->right = addCast (tree->right, resultType, TRUE);
3348 tree->opval.val = valPlus (valFromType (LETYPE (tree)),
3349 valFromType (RETYPE (tree)));
3350 tree->right = tree->left = NULL;
3351 TETYPE (tree) = getSpec (TTYPE (tree) =
3352 tree->opval.val->type);
3356 /* if the right is a pointer or left is a literal
3357 xchange left & right */
3358 if (IS_ARRAY (RTYPE (tree)) ||
3359 IS_PTR (RTYPE (tree)) ||
3360 IS_LITERAL (LTYPE (tree)))
3362 ast *tTree = tree->left;
3363 tree->left = tree->right;
3364 tree->right = tTree;
3367 /* if right is a literal and */
3368 /* left is also an addition/subtraction with a literal then */
3369 /* rearrange the tree */
3370 if (IS_LITERAL (RTYPE (tree)))
3372 ast *litTree, *parent;
3373 litTree = searchLitOp (tree, &parent, "+-");
3376 if (litTree->opval.op == '+')
3380 ast *tTree = litTree->left;
3381 litTree->left = tree->right;
3382 tree->right = tree->left;
3385 else if (litTree->opval.op == '-')
3387 if (IS_LITERAL (RTYPE (litTree)))
3391 ast *tTree = litTree->left;
3392 litTree->left = tree->right;
3393 tree->right = tTree;
3399 ast *tTree = litTree->right;
3400 litTree->right = tree->right;
3401 tree->right = tTree;
3402 litTree->opval.op = '+';
3403 tree->opval.op = '-';
3406 decorateType (parent, resultType);
3410 LRVAL (tree) = RRVAL (tree) = 1;
3411 /* if the left is a pointer */
3412 if (IS_PTR (LTYPE (tree)) || IS_AGGREGATE (LTYPE (tree)) )
3413 TETYPE (tree) = getSpec (TTYPE (tree) =
3417 tree->left = addCast (tree->left, resultType, TRUE);
3418 tree->right = addCast (tree->right, resultType, TRUE);
3419 TETYPE (tree) = getSpec (TTYPE (tree) =
3420 computeType (LTYPE (tree),
3428 /*------------------------------------------------------------------*/
3429 /*----------------------------*/
3431 /*----------------------------*/
3432 case '-': /* can be unary */
3433 /* if right is null then unary */
3437 if (!IS_ARITHMETIC (LTYPE (tree)))
3439 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3440 goto errorTreeReturn;
3443 /* if left is a literal then do it */
3444 if (IS_LITERAL (LTYPE (tree)))
3446 tree->type = EX_VALUE;
3447 tree->opval.val = valUnaryPM (valFromType (LETYPE (tree)));
3449 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3452 tree->left = addCast (tree->left, resultType, TRUE);
3453 TETYPE (tree) = getSpec (TTYPE (tree) =
3454 computeType (LTYPE (tree),
3462 /*------------------------------------------------------------------*/
3463 /*----------------------------*/
3465 /*----------------------------*/
3467 if (!(IS_PTR (LTYPE (tree)) ||
3468 IS_ARRAY (LTYPE (tree)) ||
3469 IS_ARITHMETIC (LTYPE (tree))))
3471 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3472 goto errorTreeReturn;
3475 if (!(IS_PTR (RTYPE (tree)) ||
3476 IS_ARRAY (RTYPE (tree)) ||
3477 IS_ARITHMETIC (RTYPE (tree))))
3479 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3480 goto errorTreeReturn;
3483 if ((IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree))) &&
3484 !(IS_PTR (RTYPE (tree)) || IS_ARRAY (RTYPE (tree)) ||
3485 IS_INTEGRAL (RTYPE (tree))))
3487 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-");
3488 goto errorTreeReturn;
3491 /* if they are both literal then */
3492 /* rewrite the tree */
3493 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3495 tree->type = EX_VALUE;
3496 tree->left = addCast (tree->left, resultType, TRUE);
3497 tree->right = addCast (tree->right, resultType, TRUE);
3498 tree->opval.val = valMinus (valFromType (LETYPE (tree)),
3499 valFromType (RETYPE (tree)));
3500 tree->right = tree->left = NULL;
3501 TETYPE (tree) = getSpec (TTYPE (tree) =
3502 tree->opval.val->type);
3506 /* if the left & right are equal then zero */
3507 if (isAstEqual (tree->left, tree->right))
3509 tree->type = EX_VALUE;
3510 tree->left = tree->right = NULL;
3511 tree->opval.val = constVal ("0");
3512 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3516 /* if both of them are pointers or arrays then */
3517 /* the result is going to be an integer */
3518 if ((IS_ARRAY (LTYPE (tree)) || IS_PTR (LTYPE (tree))) &&
3519 (IS_ARRAY (RTYPE (tree)) || IS_PTR (RTYPE (tree))))
3520 TETYPE (tree) = TTYPE (tree) = newIntLink ();
3522 /* if only the left is a pointer */
3523 /* then result is a pointer */
3524 if (IS_PTR (LTYPE (tree)) || IS_ARRAY (LTYPE (tree)))
3525 TETYPE (tree) = getSpec (TTYPE (tree) =
3529 tree->left = addCast (tree->left, resultType, TRUE);
3530 tree->right = addCast (tree->right, resultType, TRUE);
3532 TETYPE (tree) = getSpec (TTYPE (tree) =
3533 computeType (LTYPE (tree),
3539 LRVAL (tree) = RRVAL (tree) = 1;
3541 /* if right is a literal and */
3542 /* left is also an addition/subtraction with a literal then */
3543 /* rearrange the tree */
3544 if (IS_LITERAL (RTYPE (tree))
3545 /* avoid infinite loop */
3546 && (TYPE_TARGET_ULONG) ulFromVal (tree->right->opval.val) != 0)
3548 ast *litTree, *litParent;
3549 litTree = searchLitOp (tree, &litParent, "+-");
3552 if (litTree->opval.op == '+')
3556 ast *tTree = litTree->left;
3557 litTree->left = litTree->right;
3558 litTree->right = tree->right;
3559 tree->right = tTree;
3560 tree->opval.op = '+';
3561 litTree->opval.op = '-';
3563 else if (litTree->opval.op == '-')
3565 if (IS_LITERAL (RTYPE (litTree)))
3569 ast *tTree = litTree->left;
3570 litTree->left = tree->right;
3571 tree->right = litParent->left;
3572 litParent->left = tTree;
3573 litTree->opval.op = '+';
3575 tree->decorated = 0;
3576 decorateType (tree, resultType);
3582 ast *tTree = litTree->right;
3583 litTree->right = tree->right;
3584 tree->right = tTree;
3587 decorateType (litParent, resultType);
3592 /*------------------------------------------------------------------*/
3593 /*----------------------------*/
3595 /*----------------------------*/
3597 /* can be only integral type */
3598 if (!IS_INTEGRAL (LTYPE (tree)))
3600 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3601 goto errorTreeReturn;
3604 /* if left is a literal then do it */
3605 if (IS_LITERAL (LTYPE (tree)))
3607 tree->type = EX_VALUE;
3608 tree->opval.val = valComplement (valFromType (LETYPE (tree)));
3610 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3611 return addCast (tree, resultType, TRUE);
3614 if (resultType == RESULT_TYPE_BIT &&
3615 IS_UNSIGNED (tree->left->etype) &&
3616 getSize (tree->left->etype) < INTSIZE)
3618 /* promotion rules are responsible for this strange result:
3619 bit -> int -> ~int -> bit
3620 uchar -> int -> ~int -> bit
3622 werrorfl (tree->filename, tree->lineno, W_COMPLEMENT);
3624 /* optimize bit-result, even if we optimize a buggy source */
3625 tree->type = EX_VALUE;
3626 tree->opval.val = constVal ("1");
3629 tree->left = addCast (tree->left, resultType, TRUE);
3631 COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
3634 /*------------------------------------------------------------------*/
3635 /*----------------------------*/
3637 /*----------------------------*/
3639 /* can be pointer */
3640 if (!IS_ARITHMETIC (LTYPE (tree)) &&
3641 !IS_PTR (LTYPE (tree)) &&
3642 !IS_ARRAY (LTYPE (tree)))
3644 werrorfl (tree->filename, tree->lineno, E_UNARY_OP, tree->opval.op);
3645 goto errorTreeReturn;
3648 /* if left is another '!' */
3649 if (IS_AST_NOT_OPER (tree->left))
3651 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
3653 /* replace double '!!X' by 'X' */
3654 return tree->left->left;
3656 /* remove double '!!X' by 'X ? 1 : 0' */
3657 tree->opval.op = '?';
3658 tree->left = tree->left->left;
3659 tree->right = newNode (':',
3660 newAst_VALUE (constVal ("1")),
3661 newAst_VALUE (constVal ("0")));
3662 tree->right->lineno = tree->lineno;
3663 tree->decorated = 0;
3664 return decorateType (tree, resultType);
3667 /* if left is a literal then do it */
3668 if (IS_LITERAL (LTYPE (tree)))
3670 tree->type = EX_VALUE;
3671 tree->opval.val = valNot (valFromType (LETYPE (tree)));
3673 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3677 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3680 /*------------------------------------------------------------------*/
3681 /*----------------------------*/
3683 /*----------------------------*/
3687 TTYPE (tree) = LTYPE (tree);
3688 TETYPE (tree) = LETYPE (tree);
3693 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
3697 TTYPE (tree) = TETYPE (tree) = newCharLink();
3701 TTYPE (tree) = TETYPE (tree) = newIntLink();
3706 if (!IS_INTEGRAL (LTYPE (tree)) || !IS_INTEGRAL (tree->left->etype))
3708 werrorfl (tree->filename, tree->lineno, E_SHIFT_OP_INVALID);
3709 werrorfl (tree->filename, tree->lineno, W_CONTINUE, "left & right types are ");
3710 printTypeChain (LTYPE (tree), stderr);
3711 fprintf (stderr, ",");
3712 printTypeChain (RTYPE (tree), stderr);
3713 fprintf (stderr, "\n");
3714 goto errorTreeReturn;
3717 /* make smaller type only if it's a LEFT_OP */
3718 if (tree->opval.op == LEFT_OP)
3719 tree->left = addCast (tree->left, resultType, TRUE);
3721 /* if they are both literal then */
3722 /* rewrite the tree */
3723 if (IS_LITERAL (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))
3725 tree->type = EX_VALUE;
3726 tree->opval.val = valShift (valFromType (LETYPE (tree)),
3727 valFromType (RETYPE (tree)),
3728 (tree->opval.op == LEFT_OP ? 1 : 0));
3729 tree->right = tree->left = NULL;
3730 TETYPE (tree) = getSpec (TTYPE (tree) =
3731 tree->opval.val->type);
3735 /* see if this is a GETBYTE operation if yes
3738 ast *otree = optimizeGetByte (tree, resultType);
3741 return decorateType (otree, RESULT_TYPE_NONE);
3744 /* see if this is a GETWORD operation if yes
3747 ast *otree = optimizeGetWord (tree, resultType);
3750 return decorateType (otree, RESULT_TYPE_NONE);
3753 LRVAL (tree) = RRVAL (tree) = 1;
3754 if (tree->opval.op == LEFT_OP)
3756 TETYPE (tree) = getSpec (TTYPE (tree) =
3757 computeType (LTYPE (tree),
3764 /* no promotion necessary */
3765 TTYPE (tree) = TETYPE (tree) = copyLinkChain (LTYPE (tree));
3766 if (IS_LITERAL (TTYPE (tree)))
3767 SPEC_SCLS (TTYPE (tree)) &= ~S_LITERAL;
3770 /* if only the right side is a literal & we are
3771 shifting more than size of the left operand then zero */
3772 if (IS_LITERAL (RTYPE (tree)) &&
3773 ((TYPE_TARGET_ULONG) ulFromVal (valFromType (RETYPE (tree)))) >=
3774 (getSize (TETYPE (tree)) * 8))
3776 if (tree->opval.op==LEFT_OP ||
3777 (tree->opval.op==RIGHT_OP && SPEC_USIGN(LETYPE(tree))))
3779 werrorfl (tree->filename, tree->lineno, W_SHIFT_CHANGED,
3780 (tree->opval.op == LEFT_OP ? "left" : "right"));
3781 tree->type = EX_VALUE;
3782 tree->left = tree->right = NULL;
3783 tree->opval.val = constVal ("0");
3784 TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
3791 /*------------------------------------------------------------------*/
3792 /*----------------------------*/
3794 /*----------------------------*/
3795 case CAST: /* change the type */
3796 /* cannot cast to an aggregate type */
3797 if (IS_AGGREGATE (LTYPE (tree)))
3799 werrorfl (tree->filename, tree->lineno, E_CAST_ILLEGAL);
3800 goto errorTreeReturn;
3803 /* make sure the type is complete and sane */
3804 changePointer(LTYPE(tree));
3805 checkTypeSanity(LETYPE(tree), "(cast)");
3807 /* if 'from' and 'to' are the same remove the superfluous cast, */
3808 /* this helps other optimizations */
3809 if (compareTypeExact (LTYPE(tree), RTYPE(tree), -1) == 1)
3814 /* If code memory is read only, then pointers to code memory */
3815 /* implicitly point to constants -- make this explicit */
3817 sym_link *t = LTYPE(tree);
3818 while (t && t->next)
3820 if (IS_CODEPTR(t) && port->mem.code_ro)
3822 if (IS_SPEC(t->next))
3823 SPEC_CONST (t->next) = 1;
3825 DCL_PTR_CONST (t->next) = 1;
3832 /* if the right is a literal replace the tree */
3833 if (IS_LITERAL (RETYPE (tree))) {
3834 if (!IS_PTR (LTYPE (tree))) {
3835 tree->type = EX_VALUE;
3837 valCastLiteral (LTYPE (tree),
3838 floatFromVal (valFromType (RETYPE (tree))));
3841 TTYPE (tree) = tree->opval.val->type;
3842 tree->values.literalFromCast = 1;
3843 } else if (IS_GENPTR(LTYPE(tree)) && !IS_PTR(RTYPE(tree)) &&
3844 ((int) ulFromVal(valFromType(RETYPE(tree)))) !=0 ) /* special case of NULL */ {
3845 sym_link *rest = LTYPE(tree)->next;
3846 werrorfl (tree->filename, tree->lineno, W_LITERAL_GENERIC);
3847 TTYPE(tree) = newLink(DECLARATOR);
3848 DCL_TYPE(TTYPE(tree)) = FPOINTER;
3849 TTYPE(tree)->next = rest;
3850 tree->left->opval.lnk = TTYPE(tree);
3853 TTYPE (tree) = LTYPE (tree);
3857 TTYPE (tree) = LTYPE (tree);
3861 #if 0 // this is already checked, now this could be explicit
3862 /* if pointer to struct then check names */
3863 if (IS_PTR(LTYPE(tree)) && IS_STRUCT(LTYPE(tree)->next) &&
3864 IS_PTR(RTYPE(tree)) && IS_STRUCT(RTYPE(tree)->next) &&
3865 strcmp(SPEC_STRUCT(LETYPE(tree))->tag,SPEC_STRUCT(RETYPE(tree))->tag))
3867 werrorfl (tree->filename, tree->lineno, W_CAST_STRUCT_PTR,SPEC_STRUCT(RETYPE(tree))->tag,
3868 SPEC_STRUCT(LETYPE(tree))->tag);
3871 if (IS_ADDRESS_OF_OP(tree->right)
3872 && IS_AST_SYM_VALUE (tree->right->left)
3873 && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
3875 symbol * sym = AST_SYMBOL (tree->right->left);
3876 unsigned int gptype = 0;
3877 unsigned int addr = SPEC_ADDR (sym->etype);
3879 if (IS_GENPTR (LTYPE (tree)) && ((GPTRSIZE > FPTRSIZE)
3880 || TARGET_IS_PIC16) )
3882 switch (SPEC_SCLS (sym->etype))
3885 gptype = GPTYPE_CODE;
3888 gptype = GPTYPE_FAR;
3892 gptype = GPTYPE_NEAR;
3895 gptype = GPTYPE_XSTACK;
3900 if(TARGET_IS_PIC16 && (SPEC_SCLS(sym->etype) == S_FIXED))
3901 gptype = GPTYPE_NEAR;
3903 addr |= gptype << (8*(GPTRSIZE - 1));
3906 tree->type = EX_VALUE;
3908 valCastLiteral (LTYPE (tree), addr);
3909 TTYPE (tree) = tree->opval.val->type;
3910 TETYPE (tree) = getSpec (TTYPE (tree));
3913 tree->values.literalFromCast = 1;
3917 /* handle offsetof macro: */
3918 /* #define offsetof(TYPE, MEMBER) \ */
3919 /* ((unsigned) &((TYPE *)0)->MEMBER) */
3920 if (IS_ADDRESS_OF_OP(tree->right)
3921 && IS_AST_OP (tree->right->left)
3922 && tree->right->left->opval.op == PTR_OP
3923 && IS_AST_OP (tree->right->left->left)
3924 && tree->right->left->left->opval.op == CAST
3925 && IS_AST_LIT_VALUE(tree->right->left->left->right)) {
3927 symbol *element = getStructElement (
3928 SPEC_STRUCT (LETYPE(tree->right->left)),
3929 AST_SYMBOL(tree->right->left->right)
3933 tree->type = EX_VALUE;
3934 tree->opval.val = valCastLiteral (
3937 + floatFromVal (valFromType (RTYPE (tree->right->left->left)))
3940 TTYPE (tree) = tree->opval.val->type;
3941 TETYPE (tree) = getSpec (TTYPE (tree));
3948 /* if the right is a literal replace the tree */
3949 if (IS_LITERAL (RETYPE (tree))) {
3951 if (IS_PTR (LTYPE (tree)) && !IS_GENPTR (LTYPE (tree)) ) {
3952 /* rewrite (type *)litaddr
3954 and define type at litaddr temp
3955 (but only if type's storage class is not generic)
3957 ast *newTree = newNode ('&', NULL, NULL);
3960 TTYPE (newTree) = LTYPE (tree);
3961 TETYPE (newTree) = getSpec(LTYPE (tree));
3963 /* define a global symbol at the casted address*/
3964 sym = newSymbol(genSymName (0), 0);
3965 sym->type = LTYPE (tree)->next;
3967 sym->type = newLink (V_VOID);
3968 sym->etype = getSpec(sym->type);
3969 SPEC_SCLS (sym->etype) = sclsFromPtr (LTYPE (tree));
3970 sym->lineDef = tree->lineno;
3973 SPEC_STAT (sym->etype) = 1;
3974 SPEC_ADDR(sym->etype) = floatFromVal (valFromType (RTYPE (tree)));
3975 SPEC_ABSA(sym->etype) = 1;
3976 addSym (SymbolTab, sym, sym->name, 0, 0, 0);
3979 newTree->left = newAst_VALUE(symbolVal(sym));
3980 newTree->left->lineno = tree->lineno;
3981 LTYPE (newTree) = sym->type;
3982 LETYPE (newTree) = sym->etype;
3983 LLVAL (newTree) = 1;
3984 LRVAL (newTree) = 0;
3985 TLVAL (newTree) = 1;
3989 if (!IS_PTR (LTYPE (tree))) {
3990 tree->type = EX_VALUE;
3992 valCastLiteral (LTYPE (tree),
3993 floatFromVal (valFromType (RTYPE (tree))));
3994 TTYPE (tree) = tree->opval.val->type;
3997 tree->values.literalFromCast = 1;
3998 TETYPE (tree) = getSpec (TTYPE (tree));
4002 TTYPE (tree) = LTYPE (tree);
4006 TETYPE (tree) = getSpec (TTYPE (tree));
4010 /*------------------------------------------------------------------*/
4011 /*----------------------------*/
4012 /* logical &&, || */
4013 /*----------------------------*/
4016 /* each must be arithmetic type or be a pointer */
4017 if (!IS_PTR (LTYPE (tree)) &&
4018 !IS_ARRAY (LTYPE (tree)) &&
4019 !IS_INTEGRAL (LTYPE (tree)))
4021 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4022 goto errorTreeReturn;
4025 if (!IS_PTR (RTYPE (tree)) &&
4026 !IS_ARRAY (RTYPE (tree)) &&
4027 !IS_INTEGRAL (RTYPE (tree)))
4029 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4030 goto errorTreeReturn;
4032 /* if they are both literal then */
4033 /* rewrite the tree */
4034 if (IS_LITERAL (RTYPE (tree)) &&
4035 IS_LITERAL (LTYPE (tree)))
4037 tree->type = EX_VALUE;
4038 tree->opval.val = valLogicAndOr (valFromType (LTYPE (tree)),
4039 valFromType (RTYPE (tree)),
4041 tree->right = tree->left = NULL;
4042 TETYPE (tree) = getSpec (TTYPE (tree) =
4043 tree->opval.val->type);
4046 LRVAL (tree) = RRVAL (tree) = 1;
4047 TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4050 /*------------------------------------------------------------------*/
4051 /*----------------------------*/
4052 /* comparison operators */
4053 /*----------------------------*/
4061 ast *lt = optimizeCompare (tree);
4067 /* if they are pointers they must be castable */
4068 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4070 if (tree->opval.op==EQ_OP &&
4071 !IS_GENPTR(LTYPE(tree)) && IS_GENPTR(RTYPE(tree))) {
4072 // we cannot cast a gptr to a !gptr: switch the leaves
4073 struct ast *s=tree->left;
4074 tree->left=tree->right;
4077 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4079 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4080 fprintf (stderr, "comparing type ");
4081 printTypeChain (LTYPE (tree), stderr);
4082 fprintf (stderr, "to type ");
4083 printTypeChain (RTYPE (tree), stderr);
4084 fprintf (stderr, "\n");
4085 goto errorTreeReturn;
4088 /* else they should be promotable to one another */
4091 if (!((IS_PTR (LTYPE (tree)) && IS_LITERAL (RTYPE (tree))) ||
4092 (IS_PTR (RTYPE (tree)) && IS_LITERAL (LTYPE (tree)))))
4094 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4096 werrorfl (tree->filename, tree->lineno, E_COMPARE_OP);
4097 fprintf (stderr, "comparing type ");
4098 printTypeChain (LTYPE (tree), stderr);
4099 fprintf (stderr, "to type ");
4100 printTypeChain (RTYPE (tree), stderr);
4101 fprintf (stderr, "\n");
4102 goto errorTreeReturn;
4107 CCR_RESULT ccr_result = CCR_OK;
4109 /* if left is integral and right is literal
4110 then check constant range */
4111 if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
4112 ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
4113 tree->opval.op, FALSE);
4114 if (ccr_result == CCR_OK &&
4115 IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
4116 ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
4117 tree->opval.op, TRUE);
4120 case CCR_ALWAYS_TRUE:
4121 case CCR_ALWAYS_FALSE:
4122 if (!options.lessPedantic)
4123 werrorfl (tree->filename, tree->lineno, W_COMP_RANGE,
4124 ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
4125 return decorateType (newAst_VALUE (constVal (
4126 ccr_result == CCR_ALWAYS_TRUE ? "1" : "0")),
4134 /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
4135 if (tree->opval.op == '>' &&
4136 SPEC_USIGN(LETYPE(tree)) &&
4137 IS_LITERAL(RTYPE(tree)) &&
4138 ((int) ulFromVal (valFromType (RETYPE (tree)))) == 0)
4140 if ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT))
4142 /* the parent is an ifx: */
4143 /* if (unsigned value) */
4147 /* (unsigned value) ? 1 : 0 */
4148 tree->opval.op = '?';
4149 tree->right = newNode (':',
4150 newAst_VALUE (constVal ("1")),
4151 tree->right); /* val 0 */
4152 tree->right->lineno = tree->lineno;
4153 tree->right->left->lineno = tree->lineno;
4154 tree->decorated = 0;
4155 return decorateType (tree, resultType);
4158 /* 'ifx (op == 0)' -> 'ifx (!(op))' */
4159 if (IS_LITERAL(RTYPE(tree)) &&
4160 floatFromVal (valFromType (RETYPE (tree))) == 0 &&
4161 tree->opval.op == EQ_OP &&
4162 (resultType == RESULT_TYPE_IFX || resultType == RESULT_TYPE_BIT))
4164 tree->opval.op = '!';
4166 tree->decorated = 0;
4167 return decorateType (tree, resultType);
4170 /* if they are both literal then */
4171 /* rewrite the tree */
4172 if (IS_LITERAL (RTYPE (tree)) &&
4173 IS_LITERAL (LTYPE (tree)))
4175 tree->type = EX_VALUE;
4176 tree->opval.val = valCompare (valFromType (LETYPE (tree)),
4177 valFromType (RETYPE (tree)),
4179 tree->right = tree->left = NULL;
4180 TETYPE (tree) = getSpec (TTYPE (tree) =
4181 tree->opval.val->type);
4185 /* if one is 'signed char ' and the other one is 'unsigned char' */
4186 /* it's necessary to promote to int */
4187 if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
4188 (IS_UNSIGNED (RTYPE (tree)) != IS_UNSIGNED (LTYPE (tree))))
4190 /* Literals are 'optimized' to 'unsigned char'. Try to figure out,
4191 if it's possible to use a 'signed char' */
4193 /* is left a 'unsigned char'? */
4194 if (IS_LITERAL (RTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)) &&
4195 /* the value range of a 'unsigned char' is 0...255;
4196 if the actual value is < 128 it can be changed to signed */
4197 (int) ulFromVal (valFromType (RETYPE (tree))) < 128)
4199 /* now we've got 2 'signed char'! */
4200 SPEC_USIGN (RETYPE (tree)) = 0;
4202 /* same test for the left operand: */
4203 else if (IS_LITERAL (LTYPE (tree)) && IS_UNSIGNED (LTYPE (tree)) &&
4204 (int) ulFromVal (valFromType (LETYPE (tree))) < 128)
4206 SPEC_USIGN (LETYPE (tree)) = 0;
4210 werrorfl (tree->filename, tree->lineno, W_CMP_SU_CHAR);
4211 tree->left = addCast (tree->left , RESULT_TYPE_INT, TRUE);
4212 tree->right = addCast (tree->right, RESULT_TYPE_INT, TRUE);
4216 LRVAL (tree) = RRVAL (tree) = 1;
4217 TTYPE (tree) = TETYPE (tree) = (resultType == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
4219 /* condition transformations */
4221 unsigned transformedOp = 0;
4223 switch (tree->opval.op)
4225 case '<': /* transform (a < b) to !(a >= b) */
4227 transformedOp = GE_OP;
4229 case '>': /* transform (a > b) to !(a <= b) */
4231 transformedOp = LE_OP;
4233 case LE_OP: /* transform (a <= b) to !(a > b) */
4235 transformedOp = '>';
4237 case GE_OP: /* transform (a >= b) to !(a < b) */
4239 transformedOp = '<';
4241 case NE_OP: /* transform (a != b) to !(a == b) */
4243 transformedOp = EQ_OP;
4245 case EQ_OP: /* transform (a == b) to !(a != b) */
4247 transformedOp = NE_OP;
4254 tree->opval.op = transformedOp;
4255 tree->decorated = 0;
4256 tree = newNode ('!', tree, NULL);
4257 tree->lineno = tree->left->lineno;
4258 return decorateType (tree, resultType);
4264 /*------------------------------------------------------------------*/
4265 /*----------------------------*/
4267 /*----------------------------*/
4268 case SIZEOF: /* evaluate wihout code generation */
4269 /* change the type to a integer */
4271 int size = getSize (tree->right->ftype);
4273 SNPRINTF(buffer, sizeof(buffer), "%d", size);
4274 if (!size && !IS_VOID(tree->right->ftype))
4275 werrorfl (tree->filename, tree->lineno, E_SIZEOF_INCOMPLETE_TYPE);
4277 tree->type = EX_VALUE;
4278 tree->opval.val = constVal (buffer);
4279 tree->right = tree->left = NULL;
4280 TETYPE (tree) = getSpec (TTYPE (tree) =
4281 tree->opval.val->type);
4285 /*------------------------------------------------------------------*/
4286 /*----------------------------*/
4288 /*----------------------------*/
4290 /* return typeof enum value */
4291 tree->type = EX_VALUE;
4294 if (IS_SPEC(tree->right->ftype)) {
4295 switch (SPEC_NOUN(tree->right->ftype)) {
4297 if (SPEC_LONG(tree->right->ftype)) typeofv = TYPEOF_LONG;
4298 else typeofv = TYPEOF_INT;
4301 typeofv = TYPEOF_FLOAT;
4304 typeofv = TYPEOF_FIXED16X16;
4307 typeofv = TYPEOF_CHAR;
4310 typeofv = TYPEOF_VOID;
4313 typeofv = TYPEOF_STRUCT;
4316 typeofv = TYPEOF_BITFIELD;
4319 typeofv = TYPEOF_BIT;
4322 typeofv = TYPEOF_SBIT;
4328 switch (DCL_TYPE(tree->right->ftype)) {
4330 typeofv = TYPEOF_POINTER;
4333 typeofv = TYPEOF_FPOINTER;
4336 typeofv = TYPEOF_CPOINTER;
4339 typeofv = TYPEOF_GPOINTER;
4342 typeofv = TYPEOF_PPOINTER;
4345 typeofv = TYPEOF_IPOINTER;
4348 typeofv = TYPEOF_ARRAY;
4351 typeofv = TYPEOF_FUNCTION;
4357 SNPRINTF (buffer, sizeof(buffer), "%d", typeofv);
4358 tree->opval.val = constVal (buffer);
4359 tree->right = tree->left = NULL;
4360 TETYPE (tree) = getSpec (TTYPE (tree) =
4361 tree->opval.val->type);
4364 /*------------------------------------------------------------------*/
4365 /*----------------------------*/
4366 /* conditional operator '?' */
4367 /*----------------------------*/
4369 /* the type is value of the colon operator (on the right) */
4370 assert (IS_COLON_OP (tree->right));
4372 /* If already known then replace the tree : optimizer will do it
4373 but faster to do it here. If done before decorating tree->right
4374 this can save generating unused const strings. */
4375 if (IS_LITERAL (LTYPE (tree)))
4377 if (((int) ulFromVal (valFromType (LETYPE (tree)))) != 0)
4378 return decorateType (tree->right->left, resultTypeProp);
4380 return decorateType (tree->right->right, resultTypeProp);
4383 tree->right = decorateType (tree->right, resultTypeProp);
4385 if (IS_AST_LIT_VALUE (tree->right->left) && IS_AST_LIT_VALUE (tree->right->right) &&
4386 ((resultType == RESULT_TYPE_IFX) || (resultType == RESULT_TYPE_BIT)))
4388 double valTrue = AST_FLOAT_VALUE (tree->right->left);
4389 double valFalse = AST_FLOAT_VALUE (tree->right->right);
4391 if ((valTrue != 0) && (valFalse == 0))
4393 /* assign cond to result */
4394 tree->left->decorated = 0;
4395 return decorateType (tree->left, resultTypeProp);
4397 else if ((valTrue == 0) && (valFalse != 0))
4399 /* assign !cond to result */
4400 tree->opval.op = '!';
4401 tree->decorated = 0;
4403 return decorateType (tree, resultTypeProp);
4407 /* they have the same boolean value, make them equal */
4408 tree->right->left = tree->right->right;
4412 /* if they are equal then replace the tree */
4413 if (isAstEqual (tree->right->left, tree->right->right))
4415 return tree->right->left;
4418 TTYPE (tree) = RTYPE (tree);
4419 TETYPE (tree) = getSpec (TTYPE (tree));
4423 /* if they don't match we have a problem */
4424 if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
4425 (compareType (RTYPE (tree), LTYPE (tree)) == 0))
4427 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "conditional operator", " ");
4428 goto errorTreeReturn;
4431 TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree),
4432 resultType, tree->opval.op);
4433 TETYPE (tree) = getSpec (TTYPE (tree));
4437 #if 0 // assignment operators are converted by the parser
4438 /*------------------------------------------------------------------*/
4439 /*----------------------------*/
4440 /* assignment operators */
4441 /*----------------------------*/
4444 /* for these it must be both must be integral */
4445 if (!IS_ARITHMETIC (LTYPE (tree)) ||
4446 !IS_ARITHMETIC (RTYPE (tree)))
4448 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4449 goto errorTreeReturn;
4452 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4454 if (!tree->initMode && IS_CONSTANT (LTYPE (tree)))
4455 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4459 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, tree->opval.op==MUL_ASSIGN ? "*=" : "/=");
4460 goto errorTreeReturn;
4471 /* for these it must be both must be integral */
4472 if (!IS_INTEGRAL (LTYPE (tree)) ||
4473 !IS_INTEGRAL (RTYPE (tree)))
4475 werrorfl (tree->filename, tree->lineno, E_OPS_INTEGRAL);
4476 goto errorTreeReturn;
4479 TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree));
4481 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4482 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "&= or |= or ^= or >>= or <<=");
4486 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "&= or |= or ^= or >>= or <<=");
4487 goto errorTreeReturn;
4493 /*------------------------------------------------------------------*/
4494 /*----------------------------*/
4496 /*----------------------------*/
4498 if (!(IS_PTR (LTYPE (tree)) ||
4499 IS_ARITHMETIC (LTYPE (tree))))
4501 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4502 goto errorTreeReturn;
4505 if (!(IS_PTR (RTYPE (tree)) ||
4506 IS_ARITHMETIC (RTYPE (tree))))
4508 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "-=");
4509 goto errorTreeReturn;
4512 TETYPE (tree) = getSpec (TTYPE (tree) =
4513 computeType (LTYPE (tree),
4518 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4519 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "-=");
4523 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "-=");
4524 goto errorTreeReturn;
4530 /*------------------------------------------------------------------*/
4531 /*----------------------------*/
4533 /*----------------------------*/
4535 /* this is not a unary operation */
4536 /* if both pointers then problem */
4537 if (IS_PTR (LTYPE (tree)) && IS_PTR (RTYPE (tree)))
4539 werrorfl (tree->filename, tree->lineno, E_PTR_PLUS_PTR);
4540 goto errorTreeReturn;
4543 if (!IS_ARITHMETIC (LTYPE (tree)) && !IS_PTR (LTYPE (tree)))
4545 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4546 goto errorTreeReturn;
4549 if (!IS_ARITHMETIC (RTYPE (tree)) && !IS_PTR (RTYPE (tree)))
4551 werrorfl (tree->filename, tree->lineno, E_PLUS_INVALID, "+=");
4552 goto errorTreeReturn;
4555 TETYPE (tree) = getSpec (TTYPE (tree) =
4556 computeType (LTYPE (tree),
4561 if (!tree->initMode && IS_CONSTANT (LETYPE (tree)))
4562 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "+=");
4566 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "+=");
4567 goto errorTreeReturn;
4570 tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
4571 tree->opval.op = '=';
4576 /*------------------------------------------------------------------*/
4577 /*----------------------------*/
4578 /* straight assignemnt */
4579 /*----------------------------*/
4581 /* cannot be an aggregate */
4582 if (IS_AGGREGATE (LTYPE (tree)))
4584 werrorfl (tree->filename, tree->lineno, E_AGGR_ASSIGN);
4585 goto errorTreeReturn;
4588 /* they should either match or be castable */
4589 if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
4591 werrorfl (tree->filename, tree->lineno, E_TYPE_MISMATCH, "assignment", " ");
4592 printFromToType(RTYPE(tree),LTYPE(tree));
4595 /* if the left side of the tree is of type void
4596 then report error */
4597 if (IS_VOID (LTYPE (tree)))
4599 werrorfl (tree->filename, tree->lineno, E_CAST_ZERO);
4600 printFromToType(RTYPE(tree), LTYPE(tree));
4603 TETYPE (tree) = getSpec (TTYPE (tree) =
4607 if (!tree->initMode ) {
4608 if (IS_CONSTANT(LTYPE(tree)))
4609 werrorfl (tree->filename, tree->lineno, E_CODE_WRITE, "=");
4613 werrorfl (tree->filename, tree->lineno, E_LVALUE_REQUIRED, "=");
4614 goto errorTreeReturn;
4619 /*------------------------------------------------------------------*/
4620 /*----------------------------*/
4621 /* comma operator */
4622 /*----------------------------*/
4624 TETYPE (tree) = getSpec (TTYPE (tree) = RTYPE (tree));
4627 /*------------------------------------------------------------------*/
4628 /*----------------------------*/
4630 /*----------------------------*/
4633 /* undo any explicit pointer derefernce; PCALL will handle it instead */
4634 if (IS_FUNC (LTYPE (tree)) && tree->left->type == EX_OP)
4636 if (tree->left->opval.op == '*' && !tree->left->right)
4637 tree->left = tree->left->left;
4640 /* require a function or pointer to function */
4641 if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
4643 werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
4644 goto errorTreeReturn;
4647 /* if there are parms, make sure that
4648 parms are decorate / process / reverse only once */
4650 !tree->right->decorated)
4655 if (IS_FUNCPTR (LTYPE (tree)))
4657 functype = LTYPE (tree)->next;
4658 processFuncPtrArgs (functype);
4661 functype = LTYPE (tree);
4663 if (processParms (tree->left, FUNC_ARGS(functype),
4664 &tree->right, &parmNumber, TRUE))
4666 goto errorTreeReturn;
4669 if ((options.stackAuto || IFFUNC_ISREENT (functype)) &&
4670 !IFFUNC_ISBUILTIN(functype))
4672 reverseParms (tree->right);
4675 TTYPE (tree) = functype->next;
4676 TETYPE (tree) = getSpec (TTYPE (tree));
4680 /*------------------------------------------------------------------*/
4681 /*----------------------------*/
4682 /* return statement */
4683 /*----------------------------*/
4688 if (compareType (currFunc->type->next, RTYPE (tree)) == 0)
4690 werrorfl (tree->filename, tree->lineno, W_RETURN_MISMATCH);
4691 printFromToType (RTYPE(tree), currFunc->type->next);
4692 goto errorTreeReturn;
4695 if (IS_VOID (currFunc->type->next)
4697 !IS_VOID (RTYPE (tree)))
4699 werrorfl (tree->filename, tree->lineno, E_FUNC_VOID);
4700 goto errorTreeReturn;
4703 /* if there is going to be a casting required then add it */
4704 if (compareType (currFunc->type->next, RTYPE (tree)) < 0)
4707 decorateType (newNode (CAST,
4708 newAst_LINK (copyLinkChain (currFunc->type->next)),
4718 if (!IS_VOID (currFunc->type->next) && tree->right == NULL)
4720 werrorfl (tree->filename, tree->lineno, W_VOID_FUNC, currFunc->name);
4721 goto errorTreeReturn;
4724 TTYPE (tree) = TETYPE (tree) = NULL;
4727 /*------------------------------------------------------------------*/
4728 /*----------------------------*/
4729 /* switch statement */
4730 /*----------------------------*/
4732 /* the switch value must be an integer */
4733 if (!IS_INTEGRAL (LTYPE (tree)))
4735 werrorfl (tree->filename, tree->lineno, E_SWITCH_NON_INTEGER);
4736 goto errorTreeReturn;
4739 TTYPE (tree) = TETYPE (tree) = NULL;
4742 /*------------------------------------------------------------------*/
4743 /*----------------------------*/
4745 /*----------------------------*/
4747 tree->left = backPatchLabels (tree->left,
4750 TTYPE (tree) = TETYPE (tree) = NULL;
4753 /*------------------------------------------------------------------*/
4754 /*----------------------------*/
4756 /*----------------------------*/
4759 AST_FOR (tree, initExpr) = decorateType (
4760 resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
4761 AST_FOR (tree, condExpr) = decorateType (
4762 resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
4763 AST_FOR (tree, loopExpr) = decorateType (
4764 resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
4766 /* if the for loop is reversible then
4767 reverse it otherwise do what we normally
4773 if (isLoopReversible (tree, &sym, &init, &end))
4774 return reverseLoop (tree, sym, init, end);
4776 return decorateType (createFor (AST_FOR (tree, trueLabel),
4777 AST_FOR (tree, continueLabel),
4778 AST_FOR (tree, falseLabel),
4779 AST_FOR (tree, condLabel),
4780 AST_FOR (tree, initExpr),
4781 AST_FOR (tree, condExpr),
4782 AST_FOR (tree, loopExpr),
4783 tree->left), RESULT_TYPE_NONE);
4786 werrorfl (tree->filename, tree->lineno, E_INTERNAL_ERROR, __FILE__, __LINE__,
4787 "node PARAM shouldn't be processed here");
4788 /* but in processParams() */
4791 TTYPE (tree) = TETYPE (tree) = NULL;
4795 /* some error found this tree will be killed */
4797 TTYPE (tree) = TETYPE (tree) = newCharLink ();
4798 tree->opval.op = NULLOP;
4804 /*-----------------------------------------------------------------*/
4805 /* sizeofOp - processes size of operation */
4806 /*-----------------------------------------------------------------*/
4808 sizeofOp (sym_link * type)
4813 /* make sure the type is complete and sane */
4814 checkTypeSanity(type, "(sizeof)");
4816 /* get the size and convert it to character */
4817 SNPRINTF (buff, sizeof(buff), "%d", size = getSize (type));
4818 if (!size && !IS_VOID(type))
4819 werror (E_SIZEOF_INCOMPLETE_TYPE);
4821 /* now convert into value */
4822 return constVal (buff);
4826 #define IS_AND(ex) (ex->type == EX_OP && ex->opval.op == AND_OP )
4827 #define IS_OR(ex) (ex->type == EX_OP && ex->opval.op == OR_OP )
4828 #define IS_NOT(ex) (ex->type == EX_OP && ex->opval.op == '!' )
4829 #define IS_ANDORNOT(ex) (IS_AND(ex) || IS_OR(ex) || IS_NOT(ex))
4830 #define IS_IFX(ex) (ex->type == EX_OP && ex->opval.op == IFX )
4831 #define IS_LT(ex) (ex->type == EX_OP && ex->opval.op == '<' )
4832 #define IS_GT(ex) (ex->type == EX_OP && ex->opval.op == '>')
4834 /*-----------------------------------------------------------------*/
4835 /* backPatchLabels - change and or not operators to flow control */
4836 /*-----------------------------------------------------------------*/
4838 backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
4844 /* while-loops insert a label between the IFX and the condition,
4845 therefore look behind the label too */
4846 if (tree->opval.op == LABEL &&
4848 IS_ANDORNOT (tree->right))
4850 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4854 if (!(IS_ANDORNOT (tree)))
4857 /* if this an and */
4860 static int localLbl = 0;
4863 SNPRINTF(buffer, sizeof(buffer), "_andif_%d", localLbl++);
4864 localLabel = newSymbol (buffer, NestLevel);
4866 tree->left = backPatchLabels (tree->left, localLabel, falseLabel);
4868 /* if left is already a IFX then just change the if true label in that */
4869 if (!IS_IFX (tree->left))
4870 tree->left = newIfxNode (tree->left, localLabel, falseLabel);
4872 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4873 /* right is a IFX then just join */
4874 if (IS_IFX (tree->right))
4875 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4877 tree->right = createLabel (localLabel, tree->right);
4878 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4880 return newNode (NULLOP, tree->left, tree->right);
4883 /* if this is an or operation */
4886 static int localLbl = 0;
4889 SNPRINTF(buffer, sizeof(buffer), "_orif_%d", localLbl++);
4890 localLabel = newSymbol (buffer, NestLevel);
4892 tree->left = backPatchLabels (tree->left, trueLabel, localLabel);
4894 /* if left is already a IFX then just change the if true label in that */
4895 if (!IS_IFX (tree->left))
4896 tree->left = newIfxNode (tree->left, trueLabel, localLabel);
4898 tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
4899 /* right is a IFX then just join */
4900 if (IS_IFX (tree->right))
4901 return newNode (NULLOP, tree->left, createLabel (localLabel, tree->right));
4903 tree->right = createLabel (localLabel, tree->right);
4904 tree->right = newIfxNode (tree->right, trueLabel, falseLabel);
4906 return newNode (NULLOP, tree->left, tree->right);
4912 /* call with exchanged labels */
4913 tree->left = backPatchLabels (tree->left, falseLabel, trueLabel);
4915 /* if left isn't already a IFX */
4916 if (!IS_IFX (tree->left))
4918 tree->left = newNode (IFX, tree->left, NULL);
4919 tree->left->trueLabel = falseLabel;
4920 tree->left->falseLabel = trueLabel;
4927 tree->trueLabel = trueLabel;
4928 tree->falseLabel = falseLabel;
4935 /*-----------------------------------------------------------------*/
4936 /* createBlock - create expression tree for block */
4937 /*-----------------------------------------------------------------*/
4939 createBlock (symbol * decl, ast * body)
4943 /* if the block has nothing */
4947 ex = newNode (BLOCK, NULL, body);
4948 ex->values.sym = decl;
4955 /*-----------------------------------------------------------------*/
4956 /* createLabel - creates the expression tree for labels */
4957 /*-----------------------------------------------------------------*/
4959 createLabel (symbol * label, ast * stmnt)
4962 char name[SDCC_NAME_MAX + 1];
4965 /* must create fresh symbol if the symbol name */
4966 /* exists in the symbol table, since there can */
4967 /* be a variable with the same name as the labl */
4968 if ((csym = findSym (SymbolTab, NULL, label->name)) &&
4969 (csym->level == label->level))
4970 label = newSymbol (label->name, label->level);
4972 /* change the name before putting it in add _ */
4973 SNPRINTF(name, sizeof(name), "%s", label->name);
4975 /* put the label in the LabelSymbol table */
4976 /* but first check if a label of the same */
4978 if ((csym = findSym (LabelTab, NULL, name)))
4979 werror (E_DUPLICATE_LABEL, label->name);
4981 addSym (LabelTab, label, name, label->level, 0, 0);
4985 label->key = labelKey++;
4986 rValue = newNode (LABEL, newAst_VALUE (symbolVal (label)), stmnt);
4992 /*-----------------------------------------------------------------*/
4993 /* createCase - generates the parsetree for a case statement */
4994 /*-----------------------------------------------------------------*/
4996 createCase (ast * swStat, ast * caseVal, ast * stmnt)
4998 char caseLbl[SDCC_NAME_MAX + 1];
5002 /* if the switch statement does not exist */
5003 /* then case is out of context */
5006 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONTEXT);
5010 caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
5011 /* if not a constant then error */
5012 if (!IS_LITERAL (caseVal->ftype))
5014 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_CONSTANT);
5018 /* if not a integer than error */
5019 if (!IS_INTEGRAL (caseVal->ftype))
5021 werrorfl (caseVal->filename, caseVal->lineno, E_CASE_NON_INTEGER);
5025 /* find the end of the switch values chain */
5026 if (!(val = swStat->values.switchVals.swVals))
5027 swStat->values.switchVals.swVals = caseVal->opval.val;
5030 /* also order the cases according to value */
5032 int cVal = (int) ulFromVal (caseVal->opval.val);
5033 while (val && (int) ulFromVal (val) < cVal)
5039 /* if we reached the end then */
5042 pval->next = caseVal->opval.val;
5044 else if ((int) ulFromVal (val) == cVal)
5046 werrorfl (caseVal->filename, caseVal->lineno, E_DUPLICATE_LABEL,
5052 /* we found a value greater than */
5053 /* the current value we must add this */
5054 /* before the value */
5055 caseVal->opval.val->next = val;
5057 /* if this was the first in chain */
5058 if (swStat->values.switchVals.swVals == val)
5059 swStat->values.switchVals.swVals =
5062 pval->next = caseVal->opval.val;
5067 /* create the case label */
5068 SNPRINTF(caseLbl, sizeof(caseLbl),
5070 swStat->values.switchVals.swNum,
5071 (int) ulFromVal (caseVal->opval.val));
5073 rexpr = createLabel (newSymbol (caseLbl, 0), stmnt);
5078 /*-----------------------------------------------------------------*/
5079 /* createDefault - creates the parse tree for the default statement */
5080 /*-----------------------------------------------------------------*/
5082 createDefault (ast * swStat, ast * defaultVal, ast * stmnt)
5084 char defLbl[SDCC_NAME_MAX + 1];
5086 /* if the switch statement does not exist */
5087 /* then case is out of context */
5090 werrorfl (defaultVal->filename, defaultVal->lineno, E_CASE_CONTEXT);
5094 if (swStat->values.switchVals.swDefault)
5096 werrorfl (defaultVal->filename, defaultVal->lineno, E_DUPLICATE_LABEL,
5101 /* turn on the default flag */
5102 swStat->values.switchVals.swDefault = 1;
5104 /* create the label */
5105 SNPRINTF (defLbl, sizeof(defLbl),
5106 "_default_%d", swStat->values.switchVals.swNum);
5107 return createLabel (newSymbol (defLbl, 0), stmnt);
5110 /*-----------------------------------------------------------------*/
5111 /* createIf - creates the parsetree for the if statement */
5112 /*-----------------------------------------------------------------*/
5114 createIf (ast * condAst, ast * ifBody, ast * elseBody)
5116 static int Lblnum = 0;
5118 symbol *ifTrue, *ifFalse, *ifEnd;
5120 /* if neither exists */
5121 if (!elseBody && !ifBody) {
5122 // if there are no side effects (i++, j() etc)
5123 if (!hasSEFcalls(condAst)) {
5128 /* create the labels */
5129 SNPRINTF (buffer, sizeof(buffer), "_iffalse_%d", Lblnum);
5130 ifFalse = newSymbol (buffer, NestLevel);
5131 /* if no else body then end == false */
5136 SNPRINTF(buffer, sizeof(buffer), "_ifend_%d", Lblnum);
5137 ifEnd = newSymbol (buffer, NestLevel);
5140 SNPRINTF (buffer, sizeof(buffer), "_iftrue_%d", Lblnum);
5141 ifTrue = newSymbol (buffer, NestLevel);
5145 /* attach the ifTrue label to the top of it body */
5146 ifBody = createLabel (ifTrue, ifBody);
5147 /* attach a goto end to the ifBody if else is present */
5150 ifBody = newNode (NULLOP, ifBody,
5152 newAst_VALUE (symbolVal (ifEnd)),
5154 /* put the elseLabel on the else body */
5155 elseBody = createLabel (ifFalse, elseBody);
5156 /* out the end at the end of the body */
5157 elseBody = newNode (NULLOP,
5159 createLabel (ifEnd, NULL));
5163 ifBody = newNode (NULLOP, ifBody,
5164 createLabel (ifFalse, NULL));
5166 condAst = backPatchLabels (condAst, ifTrue, ifFalse);
5167 if (IS_IFX (condAst))
5170 ifTree = newIfxNode (condAst, ifTrue, ifFalse);
5172 return newNode (NULLOP, ifTree,
5173 newNode (NULLOP, ifBody, elseBody));
5177 /*-----------------------------------------------------------------*/
5178 /* createDo - creates parse tree for do */
5181 /* _docontinue_n: */
5182 /* condition_expression +-> trueLabel -> _dobody_n */
5184 /* +-> falseLabel-> _dobreak_n */
5186 /*-----------------------------------------------------------------*/
5188 createDo (symbol * trueLabel, symbol * continueLabel,
5189 symbol * falseLabel, ast * condAst, ast * doBody)
5194 /* if the body does not exist then it is simple */
5197 condAst = backPatchLabels (condAst, continueLabel, falseLabel);
5198 doTree = (IS_IFX (condAst) ? createLabel (continueLabel, condAst)
5199 : newNode (IFX, createLabel (continueLabel, condAst), NULL));
5200 doTree->trueLabel = continueLabel;
5201 doTree->falseLabel = NULL;
5203 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5207 /* otherwise we have a body */
5208 condAst = backPatchLabels (condAst, trueLabel, falseLabel);
5210 /* attach the body label to the top */
5211 doBody = createLabel (trueLabel, doBody);
5212 /* attach the continue label to end of body */
5213 doBody = newNode (NULLOP, doBody,
5214 createLabel (continueLabel, NULL));
5216 /* now put the break label at the end */
5217 if (IS_IFX (condAst))
5220 doTree = newIfxNode (condAst, trueLabel, falseLabel);
5222 doTree = newNode (NULLOP, doTree, createLabel (falseLabel, NULL));
5224 /* putting it together */
5225 return newNode (NULLOP, doBody, doTree);
5228 /*-----------------------------------------------------------------*/
5229 /* createFor - creates parse tree for 'for' statement */
5232 /* condExpr +-> trueLabel -> _forbody_n */
5234 /* +-> falseLabel-> _forbreak_n */
5237 /* _forcontinue_n: */
5239 /* goto _forcond_n ; */
5241 /*-----------------------------------------------------------------*/
5243 createFor (symbol * trueLabel, symbol * continueLabel,
5244 symbol * falseLabel, symbol * condLabel,
5245 ast * initExpr, ast * condExpr, ast * loopExpr,
5250 /* if loopexpression not present then we can generate it */
5251 /* the same way as a while */
5253 return newNode (NULLOP, initExpr,
5254 createWhile (trueLabel, continueLabel,
5255 falseLabel, condExpr, forBody));
5256 /* vanilla for statement */
5257 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5259 if (condExpr && !IS_IFX (condExpr))
5260 condExpr = newIfxNode (condExpr, trueLabel, falseLabel);
5263 /* attach condition label to condition */
5264 condExpr = createLabel (condLabel, condExpr);
5266 /* attach body label to body */
5267 forBody = createLabel (trueLabel, forBody);
5269 /* attach continue to forLoop expression & attach */
5270 /* goto the forcond @ and of loopExpression */
5271 loopExpr = createLabel (continueLabel,
5275 newAst_VALUE (symbolVal (condLabel)),
5277 /* now start putting them together */
5278 forTree = newNode (NULLOP, initExpr, condExpr);
5279 forTree = newNode (NULLOP, forTree, forBody);
5280 forTree = newNode (NULLOP, forTree, loopExpr);
5281 /* finally add the break label */
5282 forTree = newNode (NULLOP, forTree,
5283 createLabel (falseLabel, NULL));
5287 /*-----------------------------------------------------------------*/
5288 /* createWhile - creates parse tree for while statement */
5289 /* the while statement will be created as follows */
5291 /* _while_continue_n: */
5292 /* condition_expression +-> trueLabel -> _while_boby_n */
5294 /* +-> falseLabel -> _while_break_n */
5295 /* _while_body_n: */
5297 /* goto _while_continue_n */
5298 /* _while_break_n: */
5299 /*-----------------------------------------------------------------*/
5301 createWhile (symbol * trueLabel, symbol * continueLabel,
5302 symbol * falseLabel, ast * condExpr, ast * whileBody)
5306 /* put the continue label */
5307 condExpr = backPatchLabels (condExpr, trueLabel, falseLabel);
5308 condExpr = createLabel (continueLabel, condExpr);
5309 condExpr->lineno = 0;
5311 /* put the body label in front of the body */
5312 whileBody = createLabel (trueLabel, whileBody);
5313 whileBody->lineno = 0;
5314 /* put a jump to continue at the end of the body */
5315 /* and put break label at the end of the body */
5316 whileBody = newNode (NULLOP,
5319 newAst_VALUE (symbolVal (continueLabel)),
5320 createLabel (falseLabel, NULL)));
5322 /* put it all together */
5323 if (IS_IFX (condExpr))
5324 whileTree = condExpr;
5327 whileTree = newNode (IFX, condExpr, NULL);
5328 /* put the true & false labels in place */
5329 whileTree->trueLabel = trueLabel;
5330 whileTree->falseLabel = falseLabel;
5333 return newNode (NULLOP, whileTree, whileBody);
5336 /*-----------------------------------------------------------------*/
5337 /* isShiftRightLitVal _BitAndLitVal - helper function */
5338 /*-----------------------------------------------------------------*/
5340 isShiftRightLitVal_BitAndLitVal (ast * tree)
5342 /* if this is not a bit and */
5343 if (!IS_BITAND (tree))
5346 /* will look for tree of the form
5347 ( expr >> litval2) & litval1 */
5348 if (!IS_AST_LIT_VALUE (tree->right))
5351 if (!IS_RIGHT_OP (tree->left))
5354 if (!IS_AST_LIT_VALUE (tree->left->right))
5357 return tree->left->left;
5360 /*-----------------------------------------------------------------*/
5361 /* isBitAndPowOf2 - helper function */
5362 /*-----------------------------------------------------------------*/
5364 isBitAndPow2 (ast * tree)
5366 /* if this is not a bit and */
5367 if (!IS_BITAND (tree))
5370 /* will look for tree of the form
5371 ( expr & (1 << litval) */
5372 if (!IS_AST_LIT_VALUE (tree->right))
5375 return powof2 (AST_ULONG_VALUE (tree->right));
5378 /*-----------------------------------------------------------------*/
5379 /* optimizeGetHbit - get highest order bit of the expression */
5380 /*-----------------------------------------------------------------*/
5382 optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
5387 expr = isShiftRightLitVal_BitAndLitVal(tree);
5390 if ((AST_ULONG_VALUE (tree->right) != 1) ||
5391 ((i = AST_ULONG_VALUE (tree->left->right)) !=
5392 (j = (getSize (TTYPE (expr)) * 8 - 1))))
5395 if (!expr && (resultType == RESULT_TYPE_BIT))
5398 if (isBitAndPow2 (tree) != (signed)getSize (TTYPE (expr)) * 8 - 1)
5404 /* make sure the port supports GETHBIT */
5405 if (port->hasExtBitOp
5406 && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
5409 return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
5412 /*-----------------------------------------------------------------*/
5413 /* optimizeGetAbit - get a single bit of the expression */
5414 /*-----------------------------------------------------------------*/
5416 optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
5421 expr = isShiftRightLitVal_BitAndLitVal(tree);
5424 if (AST_ULONG_VALUE (tree->right) != 1)
5426 count = tree->left->right;
5428 if (!expr && (resultType == RESULT_TYPE_BIT))
5430 int p2 = isBitAndPow2 (tree);
5434 count = newAst_VALUE (valueFromLit (p2));
5440 /* make sure the port supports GETABIT */
5441 if (port->hasExtBitOp
5442 && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
5445 return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
5449 /*-----------------------------------------------------------------*/
5450 /* optimizeGetByte - get a byte of the expression */
5451 /*-----------------------------------------------------------------*/
5453 optimizeGetByte (ast * tree, RESULT_TYPE resultType)
5459 expr = isShiftRightLitVal_BitAndLitVal(tree);
5462 i = AST_ULONG_VALUE (tree->left->right);
5463 count = tree->left->right;
5464 if (AST_ULONG_VALUE (tree->right) != 0xFF)
5467 if (!expr && resultType == RESULT_TYPE_CHAR)
5469 /* if this is a right shift over a multiple of 8 */
5470 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5472 i = AST_ULONG_VALUE (tree->right);
5473 count = tree->right;
5477 if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
5480 /* make sure the port supports GETBYTE */
5481 if (port->hasExtBitOp
5482 && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
5485 return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
5488 /*-----------------------------------------------------------------*/
5489 /* optimizeGetWord - get two bytes of the expression */
5490 /*-----------------------------------------------------------------*/
5492 optimizeGetWord (ast * tree, RESULT_TYPE resultType)
5498 expr = isShiftRightLitVal_BitAndLitVal(tree);
5501 i = AST_ULONG_VALUE (tree->left->right);
5502 count = tree->left->right;
5503 if (AST_ULONG_VALUE (tree->right) != 0xFFFF)
5506 if (!expr && resultType == RESULT_TYPE_INT)
5508 /* if this is a right shift over a multiple of 8 */
5509 if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
5511 i = AST_ULONG_VALUE (tree->right);
5512 count = tree->right;
5516 if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
5519 /* make sure the port supports GETWORD */
5520 if (port->hasExtBitOp
5521 && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
5524 return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
5527 /*-----------------------------------------------------------------*/
5528 /* optimizeRRCRLC :- optimize for Rotate Left/Right with carry */
5529 /*-----------------------------------------------------------------*/
5531 optimizeRRCRLC (ast * root)
5533 /* will look for trees of the form
5534 (?expr << 1) | (?expr >> 7) or
5535 (?expr >> 7) | (?expr << 1) will make that
5536 into a RLC : operation ..
5538 (?expr >> 1) | (?expr << 7) or
5539 (?expr << 7) | (?expr >> 1) will make that
5540 into a RRC operation
5541 note : by 7 I mean (number of bits required to hold the
5543 /* if the root operation is not a | operation then not */
5544 if (!IS_BITOR (root))
5547 /* I have to think of a better way to match patterns this sucks */
5548 /* that aside let's start looking for the first case : I use a
5549 negative check a lot to improve the efficiency */
5550 /* (?expr << 1) | (?expr >> 7) */
5551 if (IS_LEFT_OP (root->left) &&
5552 IS_RIGHT_OP (root->right))
5555 if (!SPEC_USIGN (TETYPE (root->left->left)))
5558 if (!IS_AST_LIT_VALUE (root->left->right) ||
5559 !IS_AST_LIT_VALUE (root->right->right))
5562 /* make sure it is the same expression */
5563 if (!isAstEqual (root->left->left,
5567 if (AST_ULONG_VALUE (root->left->right) != 1)
5570 if (AST_ULONG_VALUE (root->right->right) !=
5571 (getSize (TTYPE (root->left->left)) * 8 - 1))
5574 /* make sure the port supports RLC */
5575 if (port->hasExtBitOp
5576 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5579 /* whew got the first case : create the AST */
5580 return newNode (RLC, root->left->left, NULL);
5584 /* check for second case */
5585 /* (?expr >> 7) | (?expr << 1) */
5586 if (IS_LEFT_OP (root->right) &&
5587 IS_RIGHT_OP (root->left))
5590 if (!SPEC_USIGN (TETYPE (root->left->left)))
5593 if (!IS_AST_LIT_VALUE (root->left->right) ||
5594 !IS_AST_LIT_VALUE (root->right->right))
5597 /* make sure it is the same symbol */
5598 if (!isAstEqual (root->left->left,
5602 if (AST_ULONG_VALUE (root->right->right) != 1)
5605 if (AST_ULONG_VALUE (root->left->right) !=
5606 (getSize (TTYPE (root->left->left)) * 8 - 1))
5609 /* make sure the port supports RLC */
5610 if (port->hasExtBitOp
5611 && !port->hasExtBitOp(RLC, getSize (TTYPE (root->left->left))))
5614 /* whew got the first case : create the AST */
5615 return newNode (RLC, root->left->left, NULL);
5620 /* third case for RRC */
5621 /* (?symbol >> 1) | (?symbol << 7) */
5622 if (IS_LEFT_OP (root->right) &&
5623 IS_RIGHT_OP (root->left))
5626 if (!SPEC_USIGN (TETYPE (root->left->left)))
5629 if (!IS_AST_LIT_VALUE (root->left->right) ||
5630 !IS_AST_LIT_VALUE (root->right->right))
5633 /* make sure it is the same symbol */
5634 if (!isAstEqual (root->left->left,
5638 if (AST_ULONG_VALUE (root->left->right) != 1)
5641 if (AST_ULONG_VALUE (root->right->right) !=
5642 (getSize (TTYPE (root->left->left)) * 8 - 1))
5645 /* make sure the port supports RRC */
5646 if (port->hasExtBitOp
5647 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5650 /* whew got the first case : create the AST */
5651 return newNode (RRC, root->left->left, NULL);
5655 /* fourth and last case for now */
5656 /* (?symbol << 7) | (?symbol >> 1) */
5657 if (IS_RIGHT_OP (root->right) &&
5658 IS_LEFT_OP (root->left))
5661 if (!SPEC_USIGN (TETYPE (root->left->left)))
5664 if (!IS_AST_LIT_VALUE (root->left->right) ||
5665 !IS_AST_LIT_VALUE (root->right->right))
5668 /* make sure it is the same symbol */
5669 if (!isAstEqual (root->left->left,
5673 if (AST_ULONG_VALUE (root->right->right) != 1)
5676 if (AST_ULONG_VALUE (root->left->right) !=
5677 (getSize (TTYPE (root->left->left)) * 8 - 1))
5680 /* make sure the port supports RRC */
5681 if (port->hasExtBitOp
5682 && !port->hasExtBitOp(RRC, getSize (TTYPE (root->left->left))))
5685 /* whew got the first case : create the AST */
5686 return newNode (RRC, root->left->left, NULL);
5690 /* not found return root */
5694 /*-----------------------------------------------------------------*/
5695 /* optimizeSWAP :- optimize for nibble/byte/word swaps */
5696 /*-----------------------------------------------------------------*/
5698 optimizeSWAP (ast * root)
5700 /* will look for trees of the form
5701 (?expr << 4) | (?expr >> 4) or
5702 (?expr >> 4) | (?expr << 4) will make that
5703 into a SWAP : operation ..
5704 note : by 4 I mean (number of bits required to hold the
5706 /* if the root operation is not a | operation then not */
5707 if (!IS_BITOR (root))
5710 /* (?expr << 4) | (?expr >> 4) */
5711 if ((IS_LEFT_OP (root->left) && IS_RIGHT_OP (root->right))
5712 || (IS_RIGHT_OP (root->left) && IS_LEFT_OP (root->right)))
5715 if (!SPEC_USIGN (TETYPE (root->left->left)))
5718 if (!IS_AST_LIT_VALUE (root->left->right) ||
5719 !IS_AST_LIT_VALUE (root->right->right))
5722 /* make sure it is the same expression */
5723 if (!isAstEqual (root->left->left,
5727 if (AST_ULONG_VALUE (root->left->right) !=
5728 (getSize (TTYPE (root->left->left)) * 4))
5731 if (AST_ULONG_VALUE (root->right->right) !=
5732 (getSize (TTYPE (root->left->left)) * 4))
5735 /* make sure the port supports SWAP */
5736 if (port->hasExtBitOp
5737 && !port->hasExtBitOp(SWAP, getSize (TTYPE (root->left->left))))
5740 /* found it : create the AST */
5741 return newNode (SWAP, root->left->left, NULL);
5745 /* not found return root */
5749 /*-----------------------------------------------------------------*/
5750 /* optimizeCompare - optimizes compares for bit variables */
5751 /*-----------------------------------------------------------------*/
5753 optimizeCompare (ast * root)
5755 ast *optExpr = NULL;
5758 unsigned int litValue;
5760 /* if nothing then return nothing */
5764 /* if not a compare op then do leaves */
5765 if (!IS_COMPARE_OP (root))
5767 root->left = optimizeCompare (root->left);
5768 root->right = optimizeCompare (root->right);
5772 /* if left & right are the same then depending
5773 of the operation do */
5774 if (isAstEqual (root->left, root->right))
5776 switch (root->opval.op)
5781 optExpr = newAst_VALUE (constVal ("0"));
5786 optExpr = newAst_VALUE (constVal ("1"));
5790 return decorateType (optExpr, RESULT_TYPE_NONE);
5793 vleft = (root->left->type == EX_VALUE ?
5794 root->left->opval.val : NULL);
5796 vright = (root->right->type == EX_VALUE ?
5797 root->right->opval.val : NULL);
5799 /* if left is a BITVAR in BITSPACE */
5800 /* and right is a LITERAL then */
5801 /* optimize else do nothing */
5802 if (vleft && vright &&
5803 IS_BITVAR (vleft->etype) &&
5804 IN_BITSPACE (SPEC_OCLS (vleft->etype)) &&
5805 IS_LITERAL (vright->etype))
5808 /* if right side > 1 then comparison may never succeed */
5809 if ((litValue = (int) ulFromVal (vright)) > 1)
5811 werror (W_BAD_COMPARE);
5817 switch (root->opval.op)
5819 case '>': /* bit value greater than 1 cannot be */
5820 werror (W_BAD_COMPARE);
5824 case '<': /* bit value < 1 means 0 */
5826 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5829 case LE_OP: /* bit value <= 1 means no check */
5830 optExpr = newAst_VALUE (vright);
5833 case GE_OP: /* bit value >= 1 means only check for = */
5835 optExpr = newAst_VALUE (vleft);
5840 { /* literal is zero */
5841 switch (root->opval.op)
5843 case '<': /* bit value < 0 cannot be */
5844 werror (W_BAD_COMPARE);
5848 case '>': /* bit value > 0 means 1 */
5850 optExpr = newAst_VALUE (vleft);
5853 case LE_OP: /* bit value <= 0 means no check */
5854 case GE_OP: /* bit value >= 0 means no check */
5855 werror (W_BAD_COMPARE);
5859 case EQ_OP: /* bit == 0 means ! of bit */
5860 optExpr = newNode ('!', newAst_VALUE (vleft), NULL);
5864 return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
5865 } /* end-of-if of BITVAR */
5871 /*-----------------------------------------------------------------*/
5872 /* addSymToBlock : adds the symbol to the first block we find */
5873 /*-----------------------------------------------------------------*/
5875 addSymToBlock (symbol * sym, ast * tree)
5877 /* reached end of tree or a leaf */
5878 if (!tree || IS_AST_LINK (tree) || IS_AST_VALUE (tree))
5882 if (IS_AST_OP (tree) &&
5883 tree->opval.op == BLOCK)
5886 symbol *lsym = copySymbol (sym);
5888 lsym->next = AST_VALUES (tree, sym);
5889 AST_VALUES (tree, sym) = lsym;
5893 addSymToBlock (sym, tree->left);
5894 addSymToBlock (sym, tree->right);
5897 /*-----------------------------------------------------------------*/
5898 /* processRegParms - do processing for register parameters */
5899 /*-----------------------------------------------------------------*/
5901 processRegParms (value * args, ast * body)
5905 if (IS_REGPARM (args->etype))
5906 addSymToBlock (args->sym, body);
5911 /*-----------------------------------------------------------------*/
5912 /* resetParmKey - resets the operandkeys for the symbols */
5913 /*-----------------------------------------------------------------*/
5914 DEFSETFUNC (resetParmKey)
5927 /*------------------------------------------------------------------*/
5928 /* fixupInlineLabel - change a label in an inlined function so that */
5929 /* it is always unique no matter how many times */
5930 /* the function is inlined. */
5931 /*------------------------------------------------------------------*/
5933 fixupInlineLabel (symbol * sym)
5935 char name[SDCC_NAME_MAX + 1];
5937 SNPRINTF(name, sizeof(name), "%s_%d", sym->name, inlineState.count);
5938 strcpy (sym->name, name);
5942 /*------------------------------------------------------------------*/
5943 /* copyAstLoc - copy location information (file, line, block, etc.) */
5944 /* from one ast node to another */
5945 /*------------------------------------------------------------------*/
5947 copyAstLoc (ast * dest, ast * src)
5949 dest->lineno = src->lineno;
5950 dest->filename = src->filename;
5951 dest->level = src->level;
5952 dest->block = src->block;
5953 dest->seqPoint = src->seqPoint;
5958 /*-----------------------------------------------------------------*/
5959 /* fixupInline - perform various fixups on an inline function tree */
5960 /* to take into account that it is no longer a */
5961 /* stand-alone function. */
5962 /*-----------------------------------------------------------------*/
5964 fixupInline (ast * tree, int level)
5966 tree->block = currBlockno;
5968 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
5975 /* Add any declared variables back into the symbol table */
5976 decls = tree->values.sym;
5979 decls->level = level;
5980 decls->block = currBlockno;
5981 addSym (SymbolTab, decls, decls->name, decls->level, decls->block, 0);
5982 decls = decls->next;
5986 tree->level = level;
5988 /* Update symbols */
5989 if (IS_AST_VALUE (tree) &&
5990 tree->opval.val->sym)
5992 symbol * sym = tree->opval.val->sym;
5995 sym->block = currBlockno;
5998 SYM_SPIL_LOC (sym) = NULL;
6001 /* If the symbol is a label, we need to renumber it */
6003 fixupInlineLabel (sym);
6006 /* Update IFX target labels */
6007 if (tree->type == EX_OP && tree->opval.op == IFX)
6009 if (tree->trueLabel)
6010 fixupInlineLabel (tree->trueLabel);
6011 if (tree->falseLabel)
6012 fixupInlineLabel (tree->falseLabel);
6015 /* Replace RETURN with optional assignment and a GOTO to the end */
6016 /* of the inlined function */
6017 if (tree->type == EX_OP && tree->opval.op == RETURN)
6019 ast * assignTree = NULL;
6022 if (inlineState.retsym && tree->right)
6024 assignTree = newNode ('=',
6025 newAst_VALUE (symbolVal (inlineState.retsym)),
6027 copyAstLoc (assignTree, tree);
6030 gotoTree = newNode (GOTO,
6031 newAst_VALUE (symbolVal (inlineState.retlab)),
6033 copyAstLoc (gotoTree, tree);
6035 tree->opval.op = NULLOP;
6036 tree->left = assignTree;
6037 tree->right = gotoTree;
6040 /* Update any children */
6042 fixupInline (tree->left, level);
6044 fixupInline (tree->right, level);
6046 if (IS_AST_OP (tree) && (tree->opval.op == LABEL))
6048 symbol * label = tree->left->opval.val->sym;
6050 label->key = labelKey++;
6051 /* Add this label back into the symbol table */
6052 addSym (LabelTab, label, label->name, label->level, 0, 0);
6056 if (IS_AST_OP (tree) && (tree->opval.op == BLOCK))
6062 /*-----------------------------------------------------------------*/
6063 /* inlineAddDecl - add a variable declaration to an ast block. It */
6064 /* is also added to the symbol table if addSymTab */
6066 /*-----------------------------------------------------------------*/
6068 inlineAddDecl (symbol * sym, ast * block, int addSymTab)
6071 SYM_SPIL_LOC (sym) = NULL;
6075 symbol **decl = &(block->values.sym);
6077 sym->level = block->level;
6078 sym->block = block->block;
6082 if (strcmp ((*decl)->name, sym->name) == 0)
6084 decl = &( (*decl)->next );
6090 addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 0);
6096 /*-----------------------------------------------------------------*/
6097 /* inlineTempVar - create a temporary variable for inlining */
6098 /*-----------------------------------------------------------------*/
6100 inlineTempVar (sym_link * type, int level)
6104 sym = newSymbol (genSymName(level), level );
6105 sym->type = copyLinkChain (type);
6106 sym->etype = getSpec(sym->type);
6107 SPEC_SCLS (sym->etype) = S_AUTO;
6108 SPEC_OCLS (sym->etype) = NULL;
6109 SPEC_EXTR (sym->etype) = 0;
6110 SPEC_STAT (sym->etype) = 0;
6111 if IS_SPEC (sym->type)
6112 SPEC_VOLATILE (sym->type) = 0;
6114 DCL_PTR_VOLATILE (sym->type) = 0;
6115 SPEC_ABSA (sym->etype) = 0;
6121 /*-----------------------------------------------------------------*/
6122 /* inlineFindParmRecurse - recursive function for inlineFindParm */
6123 /*-----------------------------------------------------------------*/
6125 inlineFindParmRecurse (ast * parms, int *index)
6130 if (parms->type == EX_OP && parms->opval.op == PARAM)
6134 p=inlineFindParmRecurse (parms->left, index);
6137 p=inlineFindParmRecurse (parms->right, index);
6148 /*-----------------------------------------------------------------*/
6149 /* inlineFindParm - search an ast tree of parameters to find one */
6150 /* at a particular index (0=first parameter). */
6151 /* Returns NULL if not found. */
6152 /*-----------------------------------------------------------------*/
6154 inlineFindParm (ast * parms, int index)
6156 return inlineFindParmRecurse (parms, &index);
6159 /*-----------------------------------------------------------------*/
6160 /* inlineFindMaxBlockno - find maximum block number in an ast tree */
6161 /*-----------------------------------------------------------------*/
6163 inlineFindMaxBlockno (ast * tree, int maxBlockno)
6170 tempBlockno = inlineFindMaxBlockno (tree->left, maxBlockno);
6171 if (tempBlockno > maxBlockno)
6172 maxBlockno = tempBlockno;
6174 tempBlockno = inlineFindMaxBlockno (tree->right, maxBlockno);
6175 if (tempBlockno > maxBlockno)
6176 maxBlockno = tempBlockno;
6178 if (tree->block > maxBlockno)
6179 maxBlockno = tree->block;
6186 /*-----------------------------------------------------------------*/
6187 /* expandInlineFuncs - replace calls to inline functions with the */
6188 /* function itself */
6189 /*-----------------------------------------------------------------*/
6191 expandInlineFuncs (ast * tree, ast * block)
6193 if (IS_AST_OP (tree) && (tree->opval.op == CALL) && tree->left
6194 && IS_AST_VALUE (tree->left) && tree->left->opval.val->sym)
6196 symbol * func = tree->left->opval.val->sym;
6199 /* The symbol is probably not bound yet, so find the real one */
6200 csym = findSymWithLevel (SymbolTab, func);
6204 /* Is this an inline function that we can inline? */
6205 if (IFFUNC_ISINLINE (func->type) && func->funcTree)
6207 symbol * retsym = NULL;
6215 /* Generate a label for the inlined function to branch to */
6216 /* in case it contains a return statement */
6217 retlab = newSymbol (genSymName(tree->level+1), tree->level+1 );
6220 inlineState.retlab = retlab;
6222 /* Build the subtree for the inlined function in the form: */
6223 /* { //inlinetree block */
6224 /* { //inlinetree2 block */
6225 /* inline_function_code; */
6229 temptree = newNode (LABEL, newAst_VALUE (symbolVal (retlab)), NULL);
6230 copyAstLoc (temptree, tree);
6231 temptree = newNode (NULLOP, copyAst (func->funcTree), temptree);
6232 copyAstLoc (temptree, tree);
6233 temptree = newNode (BLOCK, NULL, temptree);
6234 copyAstLoc (temptree, tree);
6235 inlinetree2 = temptree;
6236 inlinetree = newNode (BLOCK, NULL, inlinetree2);
6237 copyAstLoc (inlinetree, tree);
6239 /* To pass parameters to the inlined function, we need some */
6240 /* intermediate variables. This avoids scoping problems */
6241 /* when the parameter declaration names are used differently */
6242 /* during the function call. For example, a function */
6243 /* declared as func(int x, int y) but called as func(y,x). */
6244 /* { //inlinetree block */
6245 /* type1 temparg1; */
6247 /* typen tempargn; */
6248 /* temparg1 = argument1; */
6250 /* tempargn = argumentn; */
6251 /* { //inlinetree2 block */
6255 /* param1 = temparg1; */
6257 /* paramn = tempargn; */
6258 /* inline_function_code; */
6262 args = FUNC_ARGS (func->type);
6269 symbol * parm = copySymbol (args->sym);
6271 temparg = inlineTempVar (args->sym->type, tree->level+1);
6272 inlineAddDecl (temparg, inlinetree, FALSE);
6274 passedarg = inlineFindParm (tree->right, argIndex);
6275 assigntree = newNode ('=',
6276 newAst_VALUE (symbolVal (temparg)),
6278 inlinetree->right = newNode (NULLOP,
6282 inlineAddDecl (parm, inlinetree2, FALSE);
6285 assigntree = newNode ('=',
6286 newAst_VALUE (symbolVal (parm)),
6287 newAst_VALUE (symbolVal (temparg)));
6288 inlinetree2->right = newNode (NULLOP,
6290 inlinetree2->right);
6297 /* Handle the return type */
6298 if (!IS_VOID (func->type->next))
6300 /* Create a temporary symbol to hold the return value and */
6301 /* join it with the inlined function using the comma */
6302 /* operator. The fixupInline function will take care of */
6303 /* changing return statements into assignments to retsym. */
6304 /* (parameter passing and return label omitted for clarity) */
6305 /* rettype retsym; */
6307 /* {{inline_function_code}}, retsym */
6309 retsym = inlineTempVar (func->type->next, tree->level);
6310 inlineAddDecl (retsym, block, TRUE);
6312 tree->opval.op = ',';
6313 tree->left = inlinetree;
6314 tree->right = newAst_VALUE (symbolVal (retsym));
6318 tree->opval.op = NULLOP;
6320 tree->right = inlinetree;
6322 inlineState.retsym = retsym;
6324 /* Renumber the various internal counters on the inlined */
6325 /* function's tree nodes and symbols. Add the inlined */
6326 /* function's local variables to the appropriate scope(s). */
6327 /* Convert inlined return statements to an assignment to */
6328 /* retsym (if needed) and a goto retlab. */
6329 fixupInline (inlinetree, inlinetree->level);
6330 inlineState.count++;
6335 /* Recursively continue to search for functions to inline. */
6336 if (IS_AST_OP (tree))
6338 if (tree->opval.op == BLOCK)
6342 expandInlineFuncs (tree->left, block);
6344 expandInlineFuncs (tree->right, block);
6349 /*-----------------------------------------------------------------*/
6350 /* createFunction - This is the key node that calls the iCode for */
6351 /* generating the code for a function. Note code */
6352 /* is generated function by function, later when */
6353 /* add inter-procedural analysis this will change */
6354 /*-----------------------------------------------------------------*/
6356 createFunction (symbol * name, ast * body)
6362 iCode *piCode = NULL;
6365 if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
6366 fprintf (stderr, "SDCCast.c:createFunction(%s)\n", name->name);
6368 /* if check function return 0 then some problem */
6369 if (checkFunction (name, NULL) == 0)
6372 /* create a dummy block if none exists */
6374 body = newNode (BLOCK, NULL, NULL);
6378 /* check if the function name already in the symbol table */
6379 if ((csym = findSym (SymbolTab, NULL, name->name)))
6382 /* special case for compiler defined functions
6383 we need to add the name to the publics list : this
6384 actually means we are now compiling the compiler
6388 addSet (&publics, name);
6393 addSymChain (&name);
6394 allocVariables (name);
6396 name->lastLine = lexLineno;
6399 /* set the stack pointer */
6400 stackPtr = -port->stack.direction * port->stack.call_overhead;
6403 if (IFFUNC_ISISR (name->type))
6404 stackPtr -= port->stack.direction * port->stack.isr_overhead;
6406 if (IFFUNC_ISREENT (name->type) || options.stackAuto)
6408 if (options.useXstack)
6409 xstackPtr -= port->stack.direction * port->stack.reent_overhead;
6411 stackPtr -= port->stack.direction * port->stack.reent_overhead;
6414 fetype = getSpec (name->type); /* get the specifier for the function */
6415 /* if this is a reentrant function then */
6416 if (IFFUNC_ISREENT (name->type))
6419 inlineState.count = 0;
6420 savedBlockno = currBlockno;
6421 currBlockno = inlineFindMaxBlockno (body, 0);
6422 expandInlineFuncs (body, NULL);
6423 currBlockno = savedBlockno;
6425 if (FUNC_ISINLINE (name->type))
6426 name->funcTree = copyAst (body);
6428 allocParms (FUNC_ARGS(name->type)); /* allocate the parameters */
6430 /* do processing for parameters that are passed in registers */
6431 processRegParms (FUNC_ARGS(name->type), body);
6433 /* set the stack pointer */
6437 gatherImplicitVariables (body, NULL); /* move implicit variables into blocks */
6439 /* allocate & autoinit the block variables */
6440 processBlockVars (body, &stack, ALLOCATE);
6442 /* name needs to be mangled */
6443 SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name);
6445 body = resolveSymbols (body); /* resolve the symbols */
6446 body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */
6448 /* save the stack information */
6449 if (options.useXstack)
6450 name->xstack = SPEC_STAK (fetype) = stack;
6452 name->stack = SPEC_STAK (fetype) = stack;
6454 ex = newAst_VALUE (symbolVal (name)); /* create name */
6455 ex = newNode (FUNCTION, ex, body);
6456 ex->values.args = FUNC_ARGS(name->type);
6458 if (options.dump_tree)
6463 /* Do not generate code for inline functions unless extern also. */
6465 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype))
6468 /* Temporary hack: always generate code for static inline functions. */
6469 /* Ideally static inline functions should only be generated if needed. */
6470 if (FUNC_ISINLINE (name->type) && !IS_EXTERN (fetype) && !IS_STATIC (fetype))
6474 /* create the node & generate intermediate code */
6476 codeOutBuf = &code->oBuf;
6477 piCode = iCodeFromAst (ex);
6478 name->generated = 1;
6483 eBBlockFromiCode (piCode);
6485 /* if there are any statics then do them */
6488 GcurMemmap = statsg;
6489 codeOutBuf = &statsg->oBuf;
6490 eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
6496 /* dealloc the block variables */
6497 processBlockVars (body, &stack, DEALLOCATE);
6498 outputDebugStackSymbols();
6499 /* deallocate paramaters */
6500 deallocParms (FUNC_ARGS(name->type));
6502 if (IFFUNC_ISREENT (name->type))
6505 /* we are done freeup memory & cleanup */
6507 if (port->reset_labelKey) labelKey = 1;
6509 FUNC_HASBODY(name->type) = 1;
6510 addSet (&operKeyReset, name);
6511 applyToSet (operKeyReset, resetParmKey);
6516 cleanUpLevel (LabelTab, 0);
6517 cleanUpBlock (StructTab, 1);
6518 cleanUpBlock (TypedefTab, 1);
6520 xstack->syms = NULL;
6521 istack->syms = NULL;
6526 #define INDENT(x,f) { int i ; fprintf (f, "%s:%d:", tree->filename, tree->lineno); for (i=0;i < x; i++) fprintf(f," "); }
6527 /*-----------------------------------------------------------------*/
6528 /* ast_print : prints the ast (for debugging purposes) */
6529 /*-----------------------------------------------------------------*/
6531 void ast_print (ast * tree, FILE *outfile, int indent)
6536 /* can print only decorated trees */
6537 if (!tree->decorated) return;
6539 /* if any child is an error | this one is an error do nothing */
6540 if (tree->isError ||
6541 (tree->left && tree->left->isError) ||
6542 (tree->right && tree->right->isError)) {
6543 fprintf(outfile,"ERROR_NODE(%p)\n",tree);
6547 /* print the line */
6548 /* if not block & function */
6549 if (tree->type == EX_OP &&
6550 (tree->opval.op != FUNCTION &&
6551 tree->opval.op != BLOCK &&
6552 tree->opval.op != NULLOP)) {
6555 if (tree->opval.op == FUNCTION) {
6557 value *args=FUNC_ARGS(tree->left->opval.val->type);
6558 fprintf(outfile,"FUNCTION (%s=%p) type (",
6559 tree->left->opval.val->name, tree);
6560 printTypeChain (tree->left->opval.val->type->next,outfile);
6561 fprintf(outfile,") args (");
6564 fprintf (outfile, ", ");
6566 printTypeChain (args ? args->type : NULL, outfile);
6568 args= args ? args->next : NULL;
6570 fprintf(outfile,")\n");
6571 ast_print(tree->left,outfile,indent);
6572 ast_print(tree->right,outfile,indent);
6575 if (tree->opval.op == BLOCK) {
6576 symbol *decls = tree->values.sym;
6577 INDENT(indent,outfile);
6578 fprintf(outfile,"{\n");
6580 INDENT(indent+2,outfile);
6581 fprintf(outfile,"DECLARE SYMBOL (%s=%p) type (",
6582 decls->name, decls);
6583 printTypeChain(decls->type,outfile);
6584 fprintf(outfile,")\n");
6586 decls = decls->next;
6588 ast_print(tree->right,outfile,indent+2);
6589 INDENT(indent,outfile);
6590 fprintf(outfile,"}\n");
6593 if (tree->opval.op == NULLOP) {
6594 ast_print(tree->left,outfile,indent);
6595 ast_print(tree->right,outfile,indent);
6598 INDENT(indent,outfile);
6600 /*------------------------------------------------------------------*/
6601 /*----------------------------*/
6602 /* leaf has been reached */
6603 /*----------------------------*/
6604 /* if this is of type value */
6605 /* just get the type */
6606 if (tree->type == EX_VALUE) {
6608 if (IS_LITERAL (tree->opval.val->etype)) {
6609 fprintf(outfile,"CONSTANT (%p) value = ", tree);
6610 if (SPEC_USIGN (tree->opval.val->etype))
6611 fprintf(outfile,"%u", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val));
6613 fprintf(outfile,"%d", (TYPE_TARGET_LONG) ulFromVal(tree->opval.val));
6614 fprintf(outfile,", 0x%x, %f", (TYPE_TARGET_ULONG) ulFromVal(tree->opval.val),
6615 floatFromVal(tree->opval.val));
6616 } else if (tree->opval.val->sym) {
6617 /* if the undefined flag is set then give error message */
6618 if (tree->opval.val->sym->undefined) {
6619 fprintf(outfile,"UNDEFINED SYMBOL ");
6621 fprintf(outfile,"SYMBOL ");
6623 fprintf(outfile,"(%s=%p @ %p)",
6624 tree->opval.val->sym->name, tree, tree->opval.val->sym);
6627 fprintf(outfile," type (");
6628 printTypeChain(tree->ftype,outfile);
6629 fprintf(outfile,")\n");
6631 fprintf(outfile,"\n");
6636 /* if type link for the case of cast */
6637 if (tree->type == EX_LINK) {
6638 fprintf(outfile,"TYPENODE (%p) type = (",tree);
6639 printTypeChain(tree->opval.lnk,outfile);
6640 fprintf(outfile,")\n");
6645 /* depending on type of operator do */
6647 switch (tree->opval.op) {
6648 /*------------------------------------------------------------------*/
6649 /*----------------------------*/
6651 /*----------------------------*/
6653 fprintf(outfile,"ARRAY_OP (%p) type (",tree);
6654 printTypeChain(tree->ftype,outfile);
6655 fprintf(outfile,")\n");
6656 ast_print(tree->left,outfile,indent+2);
6657 ast_print(tree->right,outfile,indent+2);
6660 /*------------------------------------------------------------------*/
6661 /*----------------------------*/
6663 /*----------------------------*/
6665 fprintf(outfile,"STRUCT_ACCESS (%p) type (",tree);
6666 printTypeChain(tree->ftype,outfile);
6667 fprintf(outfile,")\n");
6668 ast_print(tree->left,outfile,indent+2);
6669 ast_print(tree->right,outfile,indent+2);
6672 /*------------------------------------------------------------------*/
6673 /*----------------------------*/
6674 /* struct/union pointer */
6675 /*----------------------------*/
6677 fprintf(outfile,"PTR_ACCESS (%p) type (",tree);
6678 printTypeChain(tree->ftype,outfile);
6679 fprintf(outfile,")\n");
6680 ast_print(tree->left,outfile,indent+2);
6681 ast_print(tree->right,outfile,indent+2);
6684 /*------------------------------------------------------------------*/
6685 /*----------------------------*/
6686 /* ++/-- operation */
6687 /*----------------------------*/
6690 fprintf(outfile,"post-");
6692 fprintf(outfile,"pre-");
6693 fprintf(outfile,"INC_OP (%p) type (",tree);
6694 printTypeChain(tree->ftype,outfile);
6695 fprintf(outfile,")\n");
6696 ast_print(tree->left,outfile,indent+2); /* postincrement case */
6697 ast_print(tree->right,outfile,indent+2); /* preincrement case */
6702 fprintf(outfile,"post-");
6704 fprintf(outfile,"pre-");
6705 fprintf(outfile,"DEC_OP (%p) type (",tree);
6706 printTypeChain(tree->ftype,outfile);
6707 fprintf(outfile,")\n");
6708 ast_print(tree->left,outfile,indent+2); /* postdecrement case */
6709 ast_print(tree->right,outfile,indent+2); /* predecrement case */
6712 /*------------------------------------------------------------------*/
6713 /*----------------------------*/
6715 /*----------------------------*/
6718 fprintf(outfile,"& (%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);
6724 fprintf(outfile,"ADDRESS_OF (%p) type (",tree);
6725 printTypeChain(tree->ftype,outfile);
6726 fprintf(outfile,")\n");
6727 ast_print(tree->left,outfile,indent+2);
6728 ast_print(tree->right,outfile,indent+2);
6731 /*----------------------------*/
6733 /*----------------------------*/
6735 fprintf(outfile,"OR (%p) type (",tree);
6736 printTypeChain(tree->ftype,outfile);
6737 fprintf(outfile,")\n");
6738 ast_print(tree->left,outfile,indent+2);
6739 ast_print(tree->right,outfile,indent+2);
6741 /*------------------------------------------------------------------*/
6742 /*----------------------------*/
6744 /*----------------------------*/
6746 fprintf(outfile,"XOR (%p) type (",tree);
6747 printTypeChain(tree->ftype,outfile);
6748 fprintf(outfile,")\n");
6749 ast_print(tree->left,outfile,indent+2);
6750 ast_print(tree->right,outfile,indent+2);
6753 /*------------------------------------------------------------------*/
6754 /*----------------------------*/
6756 /*----------------------------*/
6758 fprintf(outfile,"DIV (%p) type (",tree);
6759 printTypeChain(tree->ftype,outfile);
6760 fprintf(outfile,")\n");
6761 ast_print(tree->left,outfile,indent+2);
6762 ast_print(tree->right,outfile,indent+2);
6764 /*------------------------------------------------------------------*/
6765 /*----------------------------*/
6767 /*----------------------------*/
6769 fprintf(outfile,"MOD (%p) type (",tree);
6770 printTypeChain(tree->ftype,outfile);
6771 fprintf(outfile,")\n");
6772 ast_print(tree->left,outfile,indent+2);
6773 ast_print(tree->right,outfile,indent+2);
6776 /*------------------------------------------------------------------*/
6777 /*----------------------------*/
6778 /* address dereference */
6779 /*----------------------------*/
6780 case '*': /* can be unary : if right is null then unary operation */
6782 fprintf(outfile,"DEREF (%p) type (",tree);
6783 printTypeChain(tree->ftype,outfile);
6784 fprintf(outfile,")\n");
6785 ast_print(tree->left,outfile,indent+2);
6788 /*------------------------------------------------------------------*/
6789 /*----------------------------*/
6790 /* multiplication */
6791 /*----------------------------*/
6792 fprintf(outfile,"MULT (%p) type (",tree);
6793 printTypeChain(tree->ftype,outfile);
6794 fprintf(outfile,")\n");
6795 ast_print(tree->left,outfile,indent+2);
6796 ast_print(tree->right,outfile,indent+2);
6800 /*------------------------------------------------------------------*/
6801 /*----------------------------*/
6802 /* unary '+' operator */
6803 /*----------------------------*/
6807 fprintf(outfile,"UPLUS (%p) type (",tree);
6808 printTypeChain(tree->ftype,outfile);
6809 fprintf(outfile,")\n");
6810 ast_print(tree->left,outfile,indent+2);
6812 /*------------------------------------------------------------------*/
6813 /*----------------------------*/
6815 /*----------------------------*/
6816 fprintf(outfile,"ADD (%p) type (",tree);
6817 printTypeChain(tree->ftype,outfile);
6818 fprintf(outfile,")\n");
6819 ast_print(tree->left,outfile,indent+2);
6820 ast_print(tree->right,outfile,indent+2);
6823 /*------------------------------------------------------------------*/
6824 /*----------------------------*/
6826 /*----------------------------*/
6827 case '-': /* can be unary */
6829 fprintf(outfile,"UMINUS (%p) type (",tree);
6830 printTypeChain(tree->ftype,outfile);
6831 fprintf(outfile,")\n");
6832 ast_print(tree->left,outfile,indent+2);
6834 /*------------------------------------------------------------------*/
6835 /*----------------------------*/
6837 /*----------------------------*/
6838 fprintf(outfile,"SUB (%p) type (",tree);
6839 printTypeChain(tree->ftype,outfile);
6840 fprintf(outfile,")\n");
6841 ast_print(tree->left,outfile,indent+2);
6842 ast_print(tree->right,outfile,indent+2);
6845 /*------------------------------------------------------------------*/
6846 /*----------------------------*/
6848 /*----------------------------*/
6850 fprintf(outfile,"COMPL (%p) type (",tree);
6851 printTypeChain(tree->ftype,outfile);
6852 fprintf(outfile,")\n");
6853 ast_print(tree->left,outfile,indent+2);
6855 /*------------------------------------------------------------------*/
6856 /*----------------------------*/
6858 /*----------------------------*/
6860 fprintf(outfile,"NOT (%p) type (",tree);
6861 printTypeChain(tree->ftype,outfile);
6862 fprintf(outfile,")\n");
6863 ast_print(tree->left,outfile,indent+2);
6865 /*------------------------------------------------------------------*/
6866 /*----------------------------*/
6868 /*----------------------------*/
6870 fprintf(outfile,"RRC (%p) type (",tree);
6871 printTypeChain(tree->ftype,outfile);
6872 fprintf(outfile,")\n");
6873 ast_print(tree->left,outfile,indent+2);
6877 fprintf(outfile,"RLC (%p) type (",tree);
6878 printTypeChain(tree->ftype,outfile);
6879 fprintf(outfile,")\n");
6880 ast_print(tree->left,outfile,indent+2);
6883 fprintf(outfile,"SWAP (%p) type (",tree);
6884 printTypeChain(tree->ftype,outfile);
6885 fprintf(outfile,")\n");
6886 ast_print(tree->left,outfile,indent+2);
6889 fprintf(outfile,"GETHBIT (%p) type (",tree);
6890 printTypeChain(tree->ftype,outfile);
6891 fprintf(outfile,")\n");
6892 ast_print(tree->left,outfile,indent+2);
6895 fprintf(outfile,"GETABIT (%p) type (",tree);
6896 printTypeChain(tree->ftype,outfile);
6897 fprintf(outfile,")\n");
6898 ast_print(tree->left,outfile,indent+2);
6899 ast_print(tree->right,outfile,indent+2);
6902 fprintf(outfile,"GETBYTE (%p) type (",tree);
6903 printTypeChain(tree->ftype,outfile);
6904 fprintf(outfile,")\n");
6905 ast_print(tree->left,outfile,indent+2);
6906 ast_print(tree->right,outfile,indent+2);
6909 fprintf(outfile,"GETWORD (%p) type (",tree);
6910 printTypeChain(tree->ftype,outfile);
6911 fprintf(outfile,")\n");
6912 ast_print(tree->left,outfile,indent+2);
6913 ast_print(tree->right,outfile,indent+2);
6916 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
6917 printTypeChain(tree->ftype,outfile);
6918 fprintf(outfile,")\n");
6919 ast_print(tree->left,outfile,indent+2);
6920 ast_print(tree->right,outfile,indent+2);
6923 fprintf(outfile,"RIGHT_SHIFT (%p) type (",tree);
6924 printTypeChain(tree->ftype,outfile);
6925 fprintf(outfile,")\n");
6926 ast_print(tree->left,outfile,indent+2);
6927 ast_print(tree->right,outfile,indent+2);
6929 /*------------------------------------------------------------------*/
6930 /*----------------------------*/
6932 /*----------------------------*/
6933 case CAST: /* change the type */
6934 fprintf(outfile,"CAST (%p) from type (",tree);
6935 printTypeChain(tree->right->ftype,outfile);
6936 fprintf(outfile,") to type (");
6937 printTypeChain(tree->ftype,outfile);
6938 fprintf(outfile,")\n");
6939 ast_print(tree->right,outfile,indent+2);
6943 fprintf(outfile,"ANDAND (%p) type (",tree);
6944 printTypeChain(tree->ftype,outfile);
6945 fprintf(outfile,")\n");
6946 ast_print(tree->left,outfile,indent+2);
6947 ast_print(tree->right,outfile,indent+2);
6950 fprintf(outfile,"OROR (%p) type (",tree);
6951 printTypeChain(tree->ftype,outfile);
6952 fprintf(outfile,")\n");
6953 ast_print(tree->left,outfile,indent+2);
6954 ast_print(tree->right,outfile,indent+2);
6957 /*------------------------------------------------------------------*/
6958 /*----------------------------*/
6959 /* comparison operators */
6960 /*----------------------------*/
6962 fprintf(outfile,"GT(>) (%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,"LT(<) (%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,"LE(<=) (%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);
6983 fprintf(outfile,"GE(>=) (%p) type (",tree);
6984 printTypeChain(tree->ftype,outfile);
6985 fprintf(outfile,")\n");
6986 ast_print(tree->left,outfile,indent+2);
6987 ast_print(tree->right,outfile,indent+2);
6990 fprintf(outfile,"EQ(==) (%p) type (",tree);
6991 printTypeChain(tree->ftype,outfile);
6992 fprintf(outfile,")\n");
6993 ast_print(tree->left,outfile,indent+2);
6994 ast_print(tree->right,outfile,indent+2);
6997 fprintf(outfile,"NE(!=) (%p) type (",tree);
6998 printTypeChain(tree->ftype,outfile);
6999 fprintf(outfile,")\n");
7000 ast_print(tree->left,outfile,indent+2);
7001 ast_print(tree->right,outfile,indent+2);
7002 /*------------------------------------------------------------------*/
7003 /*----------------------------*/
7005 /*----------------------------*/
7006 case SIZEOF: /* evaluate wihout code generation */
7007 fprintf(outfile,"SIZEOF %d\n",(getSize (tree->right->ftype)));
7010 /*------------------------------------------------------------------*/
7011 /*----------------------------*/
7012 /* conditional operator '?' */
7013 /*----------------------------*/
7015 fprintf(outfile,"QUEST(?) (%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);
7023 fprintf(outfile,"COLON(:) (%p) type (",tree);
7024 printTypeChain(tree->ftype,outfile);
7025 fprintf(outfile,")\n");
7026 ast_print(tree->left,outfile,indent+2);
7027 ast_print(tree->right,outfile,indent+2);
7030 /*------------------------------------------------------------------*/
7031 /*----------------------------*/
7032 /* assignment operators */
7033 /*----------------------------*/
7035 fprintf(outfile,"MULASS(*=) (%p) type (",tree);
7036 printTypeChain(tree->ftype,outfile);
7037 fprintf(outfile,")\n");
7038 ast_print(tree->left,outfile,indent+2);
7039 ast_print(tree->right,outfile,indent+2);
7042 fprintf(outfile,"DIVASS(/=) (%p) type (",tree);
7043 printTypeChain(tree->ftype,outfile);
7044 fprintf(outfile,")\n");
7045 ast_print(tree->left,outfile,indent+2);
7046 ast_print(tree->right,outfile,indent+2);
7049 fprintf(outfile,"ANDASS(&=) (%p) type (",tree);
7050 printTypeChain(tree->ftype,outfile);
7051 fprintf(outfile,")\n");
7052 ast_print(tree->left,outfile,indent+2);
7053 ast_print(tree->right,outfile,indent+2);
7056 fprintf(outfile,"ORASS(|=) (%p) type (",tree);
7057 printTypeChain(tree->ftype,outfile);
7058 fprintf(outfile,")\n");
7059 ast_print(tree->left,outfile,indent+2);
7060 ast_print(tree->right,outfile,indent+2);
7063 fprintf(outfile,"XORASS(^=) (%p) type (",tree);
7064 printTypeChain(tree->ftype,outfile);
7065 fprintf(outfile,")\n");
7066 ast_print(tree->left,outfile,indent+2);
7067 ast_print(tree->right,outfile,indent+2);
7070 fprintf(outfile,"RSHFTASS(>>=) (%p) type (",tree);
7071 printTypeChain(tree->ftype,outfile);
7072 fprintf(outfile,")\n");
7073 ast_print(tree->left,outfile,indent+2);
7074 ast_print(tree->right,outfile,indent+2);
7077 fprintf(outfile,"LSHFTASS(<<=) (%p) type (",tree);
7078 printTypeChain(tree->ftype,outfile);
7079 fprintf(outfile,")\n");
7080 ast_print(tree->left,outfile,indent+2);
7081 ast_print(tree->right,outfile,indent+2);
7083 /*------------------------------------------------------------------*/
7084 /*----------------------------*/
7086 /*----------------------------*/
7088 fprintf(outfile,"SUBASS(-=) (%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);
7094 /*------------------------------------------------------------------*/
7095 /*----------------------------*/
7097 /*----------------------------*/
7099 fprintf(outfile,"ADDASS(+=) (%p) type (",tree);
7100 printTypeChain(tree->ftype,outfile);
7101 fprintf(outfile,")\n");
7102 ast_print(tree->left,outfile,indent+2);
7103 ast_print(tree->right,outfile,indent+2);
7105 /*------------------------------------------------------------------*/
7106 /*----------------------------*/
7107 /* straight assignemnt */
7108 /*----------------------------*/
7110 fprintf(outfile,"ASSIGN(=) (%p) type (",tree);
7111 printTypeChain(tree->ftype,outfile);
7112 fprintf(outfile,")\n");
7113 ast_print(tree->left,outfile,indent+2);
7114 ast_print(tree->right,outfile,indent+2);
7116 /*------------------------------------------------------------------*/
7117 /*----------------------------*/
7118 /* comma operator */
7119 /*----------------------------*/
7121 fprintf(outfile,"COMMA(,) (%p) type (",tree);
7122 printTypeChain(tree->ftype,outfile);
7123 fprintf(outfile,")\n");
7124 ast_print(tree->left,outfile,indent+2);
7125 ast_print(tree->right,outfile,indent+2);
7127 /*------------------------------------------------------------------*/
7128 /*----------------------------*/
7130 /*----------------------------*/
7133 fprintf(outfile,"CALL (%p) type (",tree);
7134 printTypeChain(tree->ftype,outfile);
7135 fprintf(outfile,")\n");
7136 ast_print(tree->left,outfile,indent+2);
7137 ast_print(tree->right,outfile,indent+2);
7140 fprintf(outfile,"PARMS\n");
7141 ast_print(tree->left,outfile,indent+2);
7142 if (tree->right /*&& !IS_AST_PARAM(tree->right)*/) {
7143 ast_print(tree->right,outfile,indent+2);
7146 /*------------------------------------------------------------------*/
7147 /*----------------------------*/
7148 /* return statement */
7149 /*----------------------------*/
7151 fprintf(outfile,"RETURN (%p) type (",tree);
7153 printTypeChain(tree->right->ftype,outfile);
7155 fprintf(outfile,")\n");
7156 ast_print(tree->right,outfile,indent+2);
7158 /*------------------------------------------------------------------*/
7159 /*----------------------------*/
7160 /* label statement */
7161 /*----------------------------*/
7163 fprintf(outfile,"LABEL (%p)\n",tree);
7164 ast_print(tree->left,outfile,indent+2);
7165 ast_print(tree->right,outfile,indent);
7167 /*------------------------------------------------------------------*/
7168 /*----------------------------*/
7169 /* switch statement */
7170 /*----------------------------*/
7174 fprintf(outfile,"SWITCH (%p) ",tree);
7175 ast_print(tree->left,outfile,0);
7176 for (val = tree->values.switchVals.swVals; val ; val = val->next) {
7177 INDENT(indent+2,outfile);
7178 fprintf(outfile,"CASE 0x%x GOTO _case_%d_%d\n",
7179 (int) ulFromVal(val),
7180 tree->values.switchVals.swNum,
7181 (int) ulFromVal(val));
7183 ast_print(tree->right,outfile,indent);
7186 /*------------------------------------------------------------------*/
7187 /*----------------------------*/
7189 /*----------------------------*/
7191 fprintf(outfile,"IF (%p) \n",tree);
7192 ast_print(tree->left,outfile,indent+2);
7193 if (tree->trueLabel) {
7194 INDENT(indent+2,outfile);
7195 fprintf(outfile,"NE(!=) 0 goto %s\n",tree->trueLabel->name);
7197 if (tree->falseLabel) {
7198 INDENT(indent+2,outfile);
7199 fprintf(outfile,"EQ(==) 0 goto %s\n",tree->falseLabel->name);
7201 ast_print(tree->right,outfile,indent+2);
7203 /*----------------------------*/
7204 /* goto Statement */
7205 /*----------------------------*/
7207 fprintf(outfile,"GOTO (%p) \n",tree);
7208 ast_print(tree->left,outfile,indent+2);
7209 fprintf(outfile,"\n");
7211 /*------------------------------------------------------------------*/
7212 /*----------------------------*/
7214 /*----------------------------*/
7216 fprintf(outfile,"FOR (%p) \n",tree);
7217 if (AST_FOR( tree, initExpr)) {
7218 INDENT(indent+2,outfile);
7219 fprintf(outfile,"INIT EXPR ");
7220 ast_print(AST_FOR(tree, initExpr),outfile,indent+2);
7222 if (AST_FOR( tree, condExpr)) {
7223 INDENT(indent+2,outfile);
7224 fprintf(outfile,"COND EXPR ");
7225 ast_print(AST_FOR(tree, condExpr),outfile,indent+2);
7227 if (AST_FOR( tree, loopExpr)) {
7228 INDENT(indent+2,outfile);
7229 fprintf(outfile,"LOOP EXPR ");
7230 ast_print(AST_FOR(tree, loopExpr),outfile,indent+2);
7232 fprintf(outfile,"FOR LOOP BODY \n");
7233 ast_print(tree->left,outfile,indent+2);
7236 fprintf(outfile,"CRITICAL (%p) \n",tree);
7237 ast_print(tree->left,outfile,indent+2);
7245 ast_print(t,stdout,0);
7248 /*-----------------------------------------------------------------*/
7249 /* astErrors : returns non-zero if errors present in tree */
7250 /*-----------------------------------------------------------------*/
7251 int astErrors(ast *t)
7260 if (t->type == EX_VALUE
7261 && t->opval.val->sym
7262 && t->opval.val->sym->undefined)
7265 errors += astErrors(t->left);
7266 errors += astErrors(t->right);