From c4e2d5daae13c63de360bc8b9a60a0667b8c536a Mon Sep 17 00:00:00 2001 From: bernhardheld Date: Sun, 25 Jan 2004 21:33:56 +0000 Subject: [PATCH] * src/SDCCast.c: added an additional type flow in decorateType() of opposite direction, see feature request #860006; it's enabled at runtime by setting the environment variable SDCC_NEWTYPEFLOW * src/SDCCast.h: changed prototype of decorateType() * src/SDCCglue.c (emitRegularMap): updated call of decorateType() * src/SDCCicode.c (geniCodeDivision) (geniCodeModulus): promotion from 'char' to 'int' can be omitted, if both operands are 'unsigned char'; see feature request #877103 * src/SDCCval.c: updated call of decorateType() (valBitwise): fixed bug #882876 (valMinus): added promotion (valLogicAndOr): result is unsigned (cheapestVal) (constVal): literals from 0...255 are 'unsigned char' now * src/SDCCsymt.c (computeType), * src/mcs51/gen.c (genCmpGt) (genCmpLt): literal 'unsigned char' must not cause an unsigned operation * src/pic/glue (pic14emitRegularMap), * src/pic16/glue.c (pic16emitRegularMap): updated call of decorateType() git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3150 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 21 +++ src/SDCCast.c | 399 ++++++++++++++++++++++++++++++++++------------- src/SDCCast.h | 12 +- src/SDCCglue.c | 2 +- src/SDCCicode.c | 8 +- src/SDCCsymt.c | 11 +- src/SDCCval.c | 76 ++++----- src/mcs51/gen.c | 7 +- src/pic/glue.c | 2 +- src/pic16/glue.c | 2 +- 10 files changed, 376 insertions(+), 164 deletions(-) diff --git a/ChangeLog b/ChangeLog index 459e8ea7..fbee181b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2004-01-25 Bernhard Held + + * src/SDCCast.c: added an additional type flow in decorateType() of + opposite direction, see feature request #860006; it's enabled at runtime + by setting the environment variable SDCC_NEWTYPEFLOW + * src/SDCCast.h: changed prototype of decorateType() + * src/SDCCglue.c (emitRegularMap): updated call of decorateType() + * src/SDCCicode.c (geniCodeDivision) (geniCodeModulus): promotion from + 'char' to 'int' can be omitted, if both operands are 'unsigned char'; + see feature request #877103 + * src/SDCCval.c: updated call of decorateType() + (valBitwise): fixed bug #882876 + (valMinus): added promotion + (valLogicAndOr): result is unsigned + (cheapestVal) (constVal): literals from 0...255 are 'unsigned char' now + * src/SDCCsymt.c (computeType), + * src/mcs51/gen.c (genCmpGt) (genCmpLt): literal 'unsigned char' + must not cause an unsigned operation + * src/pic/glue (pic14emitRegularMap), + * src/pic16/glue.c (pic16emitRegularMap): updated call of decorateType() + 2004-01-23 Bernhard Held * src/pic/pcode.c (PCodeID): commented out left over debug code diff --git a/src/SDCCast.c b/src/SDCCast.c index 56d37760..7cb2e49b 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -723,7 +723,7 @@ processParms (ast * func, actParm->decorated = 0; actParm->left = newNode( CAST, newAst_LINK(newIntLink()), actParm->left); - actParm = decorateType(actParm); + actParm = decorateType(actParm, RESULT_CHECK); } else { newType = newAst_LINK(INTTYPE); } @@ -743,13 +743,13 @@ processParms (ast * func, if (newType) { /* cast required; change this op to a cast. */ - ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm))); + ast *parmCopy = decorateType(resolveSymbols (copyAst (actParm)), RESULT_CHECK); actParm->type = EX_OP; actParm->opval.op = CAST; actParm->left = newType; actParm->right = parmCopy; - decorateType (actParm); + decorateType (actParm, RESULT_CHECK); } else if (actParm->type == EX_OP && actParm->opval.op == PARAM) { @@ -797,7 +797,7 @@ processParms (ast * func, /* if the parameter is castable then add the cast */ if (compareType (defParm->type, actParm->ftype) < 0) { - ast *pTree = decorateType(resolveSymbols (copyAst (actParm))); + ast *pTree = decorateType(resolveSymbols (copyAst (actParm)), RESULT_CHECK); /* now change the current one to a cast */ actParm->type = EX_OP; @@ -807,7 +807,7 @@ processParms (ast * func, actParm->etype = defParm->etype; actParm->ftype = defParm->type; actParm->decorated=0; /* force typechecking */ - decorateType (actParm); + decorateType (actParm, RESULT_CHECK); } /* make a copy and change the regparm type to the defined parm */ @@ -829,8 +829,8 @@ createIvalType (ast * sym, sym_link * type, initList * ilist) if (ilist->type == INIT_DEEP) ilist = ilist->init.deep; - iExpr = decorateType (resolveSymbols (list2expr (ilist))); - return decorateType (newNode ('=', sym, iExpr)); + iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK); + return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK); } /*-----------------------------------------------------------------*/ @@ -860,8 +860,8 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist) break; sflds->implicit = 1; lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds))); - lAst = decorateType (resolveSymbols (lAst)); - rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast))); + lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK); + rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK); } if (iloop) { @@ -891,9 +891,9 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) if (IS_CHAR (type->next)) if ((rast = createIvalCharPtr (sym, type, - decorateType (resolveSymbols (list2expr (ilist)))))) + decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK)))) - return decorateType (resolveSymbols (rast)); + return decorateType (resolveSymbols (rast), RESULT_CHECK); /* not the special case */ if (ilist->type != INIT_DEEP) @@ -909,7 +909,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) { ast *aSym; - aSym = decorateType (resolveSymbols(sym)); + aSym = decorateType (resolveSymbols(sym), RESULT_CHECK); rast = newNode(ARRAYINIT, aSym, NULL); rast->values.constlist = literalL; @@ -937,7 +937,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) ast *aSym; aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++)))); - aSym = decorateType (resolveSymbols (aSym)); + aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK); rast = createIval (aSym, type->next, iloop, rast); iloop = (iloop ? iloop->next : NULL); if (!iloop) @@ -965,7 +965,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist) DCL_ELEM (type) = size; } - return decorateType (resolveSymbols (rast)); + return decorateType (resolveSymbols (rast), RESULT_CHECK); } @@ -1019,7 +1019,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr) // now WE don't need iexpr's symbol anymore freeStringSymbol(AST_SYMBOL(iexpr)); - return decorateType (resolveSymbols (rast)); + return decorateType (resolveSymbols (rast), RESULT_CHECK); } return NULL; @@ -1038,7 +1038,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist) if (ilist->type == INIT_DEEP) ilist = ilist->init.deep; - iexpr = decorateType (resolveSymbols (list2expr (ilist))); + iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK); /* if character pointer */ if (IS_CHAR (type->next)) @@ -1076,9 +1076,9 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid) rast = createIvalType (sym, type, ilist); if (wid) - return decorateType (resolveSymbols (newNode (NULLOP, wid, rast))); + return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK); else - return decorateType (resolveSymbols (rast)); + return decorateType (resolveSymbols (rast), RESULT_CHECK); } /*-----------------------------------------------------------------*/ @@ -1294,7 +1294,7 @@ bool constExprTree (ast *cexpr) { return TRUE; } - cexpr = decorateType (resolveSymbols (cexpr)); + cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK); switch (cexpr->type) { @@ -1358,7 +1358,7 @@ bool constExprTree (ast *cexpr) { value * constExprValue (ast * cexpr, int check) { - cexpr = decorateType (resolveSymbols (cexpr)); + cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK); /* if this is not a constant then */ if (!IS_LITERAL (cexpr->ftype)) @@ -1951,7 +1951,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end) rloop)))); rloop->lineno=init->lineno; - return decorateType (rloop); + return decorateType (rloop, RESULT_CHECK); } @@ -2005,15 +2005,122 @@ searchLitOp (ast *tree, ast **parent, const char *ops) } /*-----------------------------------------------------------------*/ -/* decorateType - compute type for this tree also does type checking */ -/* this is done bottom up, since type have to flow upwards */ -/* it also does constant folding, and paramater checking */ +/* getResultFromType */ /*-----------------------------------------------------------------*/ +static RESULT_TYPE +getResultTypeFromType (sym_link *type) +{ + /* type = getSpec (type); */ + if (IS_BITVAR (type)) + return RESULT_TYPE_BIT; + if (IS_BITFIELD (type)) + return RESULT_TYPE_CHAR; + if (IS_CHAR (type)) + return RESULT_TYPE_CHAR; + if ( IS_INT (type) + && !IS_LONG (type)) + return RESULT_TYPE_INT; + return RESULT_TYPE_OTHER; +} + +/*-----------------------------------------------------------------*/ +/* addCast - adds casts to a type specified by RESULT_TYPE */ +/*-----------------------------------------------------------------*/ +static void +addCast (ast **tree, RESULT_TYPE resultType) +{ + sym_link *newLink; + + switch (resultType) + { + case RESULT_TYPE_CHAR: + if (getSize ((*tree)->etype) <= 1) + return; + newLink = newCharLink(); + break; + case RESULT_TYPE_INT: +#if 0 + /* casting from long to int costs additional 4 bytes dram! */ + if (getSize ((*tree)->etype) <= INTSIZE) + return; + newLink = newIntLink(); + break; +#else + /* warn ("Loosing significant digits"); */ + return; +#endif + default: + return; + } + (*tree)->decorated = 0; + *tree = newNode (CAST, newAst_LINK (newLink), *tree); + /* keep unsigned type */ + SPEC_USIGN ((*tree)->left->opval.lnk) = IS_UNSIGNED ((*tree)->right->etype) ? 1 : 0; + *tree = decorateType (*tree, resultType); +} + +/*-----------------------------------------------------------------*/ +/* resultTypePropagate - decides if resultType can be propagated */ +/*-----------------------------------------------------------------*/ +static RESULT_TYPE +resultTypePropagate (ast *tree, RESULT_TYPE resultType) +{ + switch (tree->opval.op) + { + case '=': + case '?': + case ':': + case '|': + case '^': + return resultType; + case '&': + if (!tree->right) + /* can be unary */ + return RESULT_TYPE_NONE; + else + return resultType; + default: + return RESULT_TYPE_NONE; + } +} + +/*-----------------------------------------------------------------*/ +/* getLeftResultType - gets type from left branch for propagation */ +/*-----------------------------------------------------------------*/ +static RESULT_TYPE +getLeftResultType (ast *tree, RESULT_TYPE resultType) +{ + switch (tree->opval.op) + { + case '=': + case CAST: + if (IS_PTR (tree->left->ftype)) + return RESULT_TYPE_NONE; + else + return getResultTypeFromType (tree->left->etype); + case RETURN: + if (IS_PTR (currFunc->type->next)) + return RESULT_TYPE_NONE; + else + return getResultTypeFromType (currFunc->type->next); + default: + return resultType; + } +} + +/*--------------------------------------------------------------------*/ +/* decorateType - compute type for this tree, also does type checking.*/ +/* This is done bottom up, since type has to flow upwards. */ +/* resultType flows top-down and forces e.g. char-arithmetik, if the */ +/* result is a char and the operand(s) are int's. */ +/* It also does constant folding, and parameter checking. */ +/*--------------------------------------------------------------------*/ ast * -decorateType (ast * tree) +decorateType (ast * tree, RESULT_TYPE resultType) { int parmNumber; sym_link *p; + RESULT_TYPE resultTypeProp; if (!tree) return tree; @@ -2045,7 +2152,7 @@ decorateType (ast * tree) /*------------------------------------------------------------------*/ /*----------------------------*/ - /* leaf has been reached */ +/* leaf has been reached */ /*----------------------------*/ lineno=tree->lineno; /* if this is of type value */ @@ -2130,11 +2237,26 @@ decorateType (ast * tree) } } #endif + + /* Before decorating the left branch we've to decide in dependence + upon tree->opval.op, if resultType can be propagated */ + if (getenv ("SDCC_NEWTYPEFLOW")) + resultTypeProp = resultTypePropagate (tree, resultType); + else + resultTypeProp = RESULT_TYPE_NONE; /* provide initialization */ + + dtl = decorateType (tree->left, resultTypeProp); + + /* After decorating the left branch there's type information available + in tree->left->?type. If the op is e.g. '=' we extract the type + information from there and propagate it to the right branch. */ + if (getenv ("SDCC_NEWTYPEFLOW")) + resultTypeProp = getLeftResultType (tree, resultTypeProp); - dtl = decorateType (tree->left); - /* delay right side for '?' operator since conditional macro expansions might - rely on this */ - dtr = (tree->opval.op == '?' ? tree->right : decorateType (tree->right)); + /* delay right side for '?' operator since conditional macro expansions + might rely on this */ + dtr = tree->opval.op == '?' ? tree->right : + decorateType (tree->right, resultTypeProp); /* this is to take care of situations when the tree gets rewritten */ @@ -2145,25 +2267,28 @@ decorateType (ast * tree) if ((dtl && dtl->isError) || (dtr && dtr->isError)) return tree; - if (IS_AST_OP(tree) && - (tree->opval.op == CAST || tree->opval.op == '=') && - (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) && - (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) { - // this is a cast/assign to a bigger type - if (IS_AST_OP(tree->right) && - IS_INTEGRAL(tree->right->ftype) && - (tree->right->opval.op == LEFT_OP || - tree->right->opval.op == '*' || - tree->right->opval.op == '+' || - tree->right->opval.op == '-') && - tree->right->right) { - // we should cast an operand instead of the result - tree->right->decorated = 0; - tree->right->left = newNode( CAST, newAst_LINK(newIntLink()), - tree->right->left); - tree->right = decorateType(tree->right); + if (!getenv ("SDCC_NEWTYPEFLOW")) + { + if (IS_AST_OP(tree) && + (tree->opval.op == CAST || tree->opval.op == '=') && + (getSize(LTYPE(tree)) > getSize(RTYPE(tree))) && + (getSize(RTYPE(tree)) < (unsigned) INTSIZE)) { + /* this is a cast/assign to a bigger type */ + if (IS_AST_OP(tree->right) && + IS_INTEGRAL(tree->right->ftype) && + (tree->right->opval.op == LEFT_OP || + tree->right->opval.op == '*' || + tree->right->opval.op == '+' || + tree->right->opval.op == '-') && + tree->right->right) { + /* we should cast an operand instead of the result */ + tree->right->decorated = 0; + tree->right->left = newNode( CAST, newAst_LINK(newIntLink()), + tree->right->left); + tree->right = decorateType(tree->right, RESULT_CHECK); + } + } } - } } /* depending on type of operator do */ @@ -2378,11 +2503,15 @@ decorateType (ast * tree) ast *otree = optimizeGetHbit (tree); if (otree != tree) - return decorateType (otree); + return decorateType (otree, RESULT_CHECK); } - TTYPE (tree) = - computeType (LTYPE (tree), RTYPE (tree), FALSE); + if (getenv ("SDCC_NEWTYPEFLOW")) + { + addCast (&tree->left, resultType); + addCast (&tree->right, resultType); + } + TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), FALSE); TETYPE (tree) = getSpec (TTYPE (tree)); /* if left is a literal exchange left & right */ @@ -2406,11 +2535,12 @@ decorateType (ast * tree) litTree->left = tree->right; tree->right = tTree; /* both operands in tTree are literal now */ - decorateType (parent); + decorateType (parent, RESULT_CHECK); } } LRVAL (tree) = RRVAL (tree) = 1; + return tree; } @@ -2504,11 +2634,11 @@ decorateType (ast * tree) { ast *wtree = optimizeRRCRLC (tree); if (wtree != tree) - return decorateType (wtree); + return decorateType (wtree, RESULT_CHECK); wtree = optimizeSWAP (tree); if (wtree != tree) - return decorateType (wtree); + return decorateType (wtree, RESULT_CHECK); } /* if left is a literal exchange left & right */ @@ -2532,7 +2662,7 @@ decorateType (ast * tree) litTree->left = tree->right; tree->right = tTree; /* both operands in tTree are literal now */ - decorateType (parent); + decorateType (parent, RESULT_CHECK); } } /* fall through */ @@ -2589,11 +2719,16 @@ decorateType (ast * tree) litTree->left = tree->right; tree->right = tTree; /* both operands in litTree are literal now */ - decorateType (parent); + decorateType (parent, RESULT_CHECK); } } LRVAL (tree) = RRVAL (tree) = 1; + if (getenv ("SDCC_NEWTYPEFLOW")) + { + addCast (&tree->left, resultType); + addCast (&tree->right, resultType); + } TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), @@ -2628,7 +2763,7 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - TRUE)); + ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree))))); /* if right is a literal and */ /* left is also a division by a literal then */ @@ -2648,15 +2783,15 @@ decorateType (ast * tree) litTree->right->lineno = tree->lineno; tree->right->opval.val = constVal ("1"); - decorateType (parent); + decorateType (parent, RESULT_CHECK); } else { /* litTree->left is literal: no gcse possible. - We can't call decorateType(parent), because + We can't call decorateType(parent, RESULT_CHECK), because this would cause an infinit loop. */ parent->decorated = 1; - decorateType (litTree); + decorateType (litTree, RESULT_CHECK); } } } @@ -2694,7 +2829,7 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = computeType (LTYPE (tree), RTYPE (tree), - TRUE)); + ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree))))); return tree; /*------------------------------------------------------------------*/ @@ -2799,16 +2934,26 @@ decorateType (ast * tree) litTree->left = tree->right; tree->right = tTree; /* both operands in litTree are literal now */ - decorateType (parent); + decorateType (parent, RESULT_CHECK); } } LRVAL (tree) = RRVAL (tree) = 1; - TETYPE (tree) = getSpec (TTYPE (tree) = - computeType (LTYPE (tree), - RTYPE (tree), - TRUE)); - + if (!getenv ("SDCC_NEWTYPEFLOW")) + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + TRUE)); + else + { + addCast (&tree->left, resultType); + addCast (&tree->right, resultType); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + } + return tree; /*------------------------------------------------------------------*/ @@ -2926,7 +3071,7 @@ decorateType (ast * tree) tree->opval.op = '-'; } } - decorateType (parent); + decorateType (parent, RESULT_CHECK); } } @@ -2936,10 +3081,21 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); else - TETYPE (tree) = getSpec (TTYPE (tree) = - computeType (LTYPE (tree), - RTYPE (tree), - FALSE)); + if (!getenv ("SDCC_NEWTYPEFLOW")) + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + FALSE)); + else + { + addCast (&tree->left, resultType); + addCast (&tree->right, resultType); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + } + return tree; /*------------------------------------------------------------------*/ @@ -3036,10 +3192,20 @@ decorateType (ast * tree) TETYPE (tree) = getSpec (TTYPE (tree) = LTYPE (tree)); else - TETYPE (tree) = getSpec (TTYPE (tree) = - computeType (LTYPE (tree), - RTYPE (tree), - FALSE)); + if (!getenv ("SDCC_NEWTYPEFLOW")) + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + FALSE)); + else + { + addCast (&tree->left, resultType); + addCast (&tree->right, resultType); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + } LRVAL (tree) = RRVAL (tree) = 1; @@ -3080,7 +3246,7 @@ decorateType (ast * tree) tree->right = tTree; } } - decorateType (litParent); + decorateType (litParent, RESULT_CHECK); } } return tree; @@ -3182,11 +3348,20 @@ decorateType (ast * tree) LRVAL (tree) = RRVAL (tree) = 1; if (tree->opval.op == LEFT_OP) { - /* promote char to int */ - TETYPE (tree) = getSpec (TTYPE (tree) = - computeType (LTYPE (tree), - LTYPE (tree), /* no, not RTYPE! */ - TRUE)); + if (!getenv ("SDCC_NEWTYPEFLOW")) + /* promote char to int */ + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + LTYPE (tree), /* no, not RTYPE! */ + TRUE)); + else + { + addCast (&tree->left, resultType); + TETYPE (tree) = getSpec (TTYPE (tree) = + computeType (LTYPE (tree), + RTYPE (tree), + resultType == RESULT_TYPE_CHAR ? FALSE : TRUE)); + } } else /* RIGHT_OP */ { @@ -3496,7 +3671,9 @@ decorateType (ast * tree) } /* if unsigned value < 0 then always false */ /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */ - if (SPEC_USIGN(LETYPE(tree)) && IS_LITERAL(RTYPE(tree)) && + if (SPEC_USIGN(LETYPE(tree)) && + !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */ + IS_LITERAL(RTYPE(tree)) && ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0) { if (tree->opval.op == '<') @@ -3513,7 +3690,7 @@ decorateType (ast * tree) tree->right); /* val 0 */ tree->right->lineno = tree->lineno; tree->right->left->lineno = tree->lineno; - decorateType (tree->right); + decorateType (tree->right, RESULT_CHECK); } } /* if they are both literal then */ @@ -3630,20 +3807,22 @@ decorateType (ast * tree) /*----------------------------*/ case '?': /* the type is value of the colon operator (on the right) */ - assert(IS_COLON_OP(tree->right)); + assert (IS_COLON_OP (tree->right)); /* if already known then replace the tree : optimizer will do it but faster to do it here */ - if (IS_LITERAL (LTYPE(tree))) { - if ( ((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) { - return decorateType(tree->right->left) ; - } else { - return decorateType(tree->right->right) ; - } - } else { - tree->right = decorateType(tree->right); - TTYPE (tree) = RTYPE(tree); + if (IS_LITERAL (LTYPE (tree))) + { + if (((int) floatFromVal (valFromType (LETYPE (tree)))) != 0) + return decorateType (tree->right->left, resultTypeProp); + else + return decorateType (tree->right->right, resultTypeProp); + } + else + { + tree->right = decorateType (tree->right, resultTypeProp); + TTYPE (tree) = RTYPE (tree); TETYPE (tree) = getSpec (TTYPE (tree)); - } + } return tree; case ':': @@ -3790,7 +3969,7 @@ decorateType (ast * tree) goto errorTreeReturn; } - tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right)); + tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK); tree->opval.op = '='; return tree; @@ -3897,13 +4076,14 @@ decorateType (ast * tree) goto errorTreeReturn; } - /* if there is going to be a casing required then add it */ + /* if there is going to be a casting required then add it */ if (compareType (currFunc->type->next, RTYPE (tree)) < 0) { tree->right = decorateType (newNode (CAST, - newAst_LINK (copyLinkChain (currFunc->type->next)), - tree->right)); + newAst_LINK (copyLinkChain (currFunc->type->next)), + tree->right), + RESULT_CHECK); } RRVAL (tree) = 1; @@ -3952,9 +4132,9 @@ decorateType (ast * tree) /*----------------------------*/ case FOR: - decorateType (resolveSymbols (AST_FOR (tree, initExpr))); - decorateType (resolveSymbols (AST_FOR (tree, condExpr))); - decorateType (resolveSymbols (AST_FOR (tree, loopExpr))); + decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK); + decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK); + decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK); /* if the for loop is reversible then reverse it otherwise do what we normally @@ -3973,7 +4153,7 @@ decorateType (ast * tree) AST_FOR (tree, initExpr), AST_FOR (tree, condExpr), AST_FOR (tree, loopExpr), - tree->left)); + tree->left), RESULT_CHECK); } default: TTYPE (tree) = TETYPE (tree) = NULL; @@ -4189,7 +4369,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt) return NULL; } - caseVal = decorateType (resolveSymbols (caseVal)); + caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK); /* if not a constant then error */ if (!IS_LITERAL (caseVal->ftype)) { @@ -4547,7 +4727,7 @@ optimizeGetHbit (ast * tree) && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left)))) return tree; - return decorateType (newNode (GETHBIT, tree->left->left, NULL)); + return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK); } @@ -4814,7 +4994,7 @@ optimizeCompare (ast * root) break; } - return decorateType (optExpr); + return decorateType (optExpr, RESULT_CHECK); } vleft = (root->left->type == EX_VALUE ? @@ -4888,7 +5068,7 @@ optimizeCompare (ast * root) break; } } - return decorateType (resolveSymbols (optExpr)); + return decorateType (resolveSymbols (optExpr), RESULT_CHECK); } /* end-of-if of BITVAR */ noOptimize: @@ -5034,7 +5214,8 @@ createFunction (symbol * name, ast * body) SNPRINTF (name->rname, sizeof(name->rname), "%s%s", port->fun_prefix, name->name); body = resolveSymbols (body); /* resolve the symbols */ - body = decorateType (body); /* propagateType & do semantic checks */ + body = decorateType (body, RESULT_TYPE_NONE); /* propagateType & do semantic checks */ + ex = newAst_VALUE (symbolVal (name)); /* create name */ ex = newNode (FUNCTION, ex, body); @@ -5065,7 +5246,7 @@ createFunction (symbol * name, ast * body) { GcurMemmap = statsg; codeOutFile = statsg->oFile; - eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos)))); + eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK))); staticAutos = NULL; } diff --git a/src/SDCCast.h b/src/SDCCast.h index 649960e7..5546f107 100644 --- a/src/SDCCast.h +++ b/src/SDCCast.h @@ -170,6 +170,16 @@ ast; x == AND_ASSIGN || x == OR_ASSIGN || x == INC_OP || x == DEC_OP) #define IS_DEREF_OP(x) (( x->opval.op == '*' && x->right == NULL) || x->opval.op == '.') +typedef enum +{ + RESULT_TYPE_NONE = 0, + RESULT_CHECK = 0, /* TODO: replace all occurences with the appropriate type and remove me */ + RESULT_TYPE_BIT, + RESULT_TYPE_CHAR, + RESULT_TYPE_INT, + RESULT_TYPE_OTHER +} RESULT_TYPE; + /* forward declarations for global variables */ extern ast *staticAutos; extern FILE *codeOutFile; @@ -196,7 +206,7 @@ ast *createDefault (ast *, ast *, ast *); ast *forLoopOptForm (ast *); ast *argAst (ast *); ast *resolveSymbols (ast *); -ast *decorateType (ast *); +ast *decorateType (ast *, RESULT_TYPE); ast *createWhile (symbol *, symbol *, symbol *, ast *, ast *); ast *createIf (ast *, ast *, ast *); ast *createDo (symbol *, symbol *, symbol *, ast *, ast *); diff --git a/src/SDCCglue.c b/src/SDCCglue.c index e0f68343..fbf94e76 100644 --- a/src/SDCCglue.c +++ b/src/SDCCglue.c @@ -308,7 +308,7 @@ emitRegularMap (memmap * map, bool addPublics, bool arFlag) sym->name); } ival = newNode ('=', newAst_VALUE (symbolVal (sym)), - decorateType (resolveSymbols (list2expr (sym->ival)))); + decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK)); } codeOutFile = statsg->oFile; diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 48cc6eab..d166b186 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -2059,7 +2059,9 @@ geniCodeDivision (operand * left, operand * right) sym_link *ltype = operandType (left); sym_link *letype = getSpec (ltype); - resType = usualBinaryConversions (&left, &right, TRUE, FALSE); + resType = usualBinaryConversions (&left, &right, + (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE, + FALSE); /* if the right is a literal & power of 2 and left is unsigned then make it a @@ -2098,7 +2100,9 @@ geniCodeModulus (operand * left, operand * right) return operandFromValue (valMod (left->operand.valOperand, right->operand.valOperand)); - resType = usualBinaryConversions (&left, &right, TRUE, FALSE); + resType = usualBinaryConversions (&left, &right, + (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE, + FALSE); /* now they are the same size */ ic = newiCode ('%', left, right); diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index 4b4e00c4..d3bfee79 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -1554,9 +1554,16 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt) SPEC_NOUN (reType) = V_INT; if ( ( ( SPEC_USIGN (etype1) - && (getSize (etype1) >= getSize (reType))) + /* if this operand is promoted to a larger + type don't check it's signedness */ + && (getSize (etype1) >= getSize (reType)) + /* We store signed literals in the range 0...255 as + 'unsigned char'. If there was no promotion to 'signed int' + they must not force an unsigned operation: */ + && !(IS_CHAR (etype1) && IS_LITERAL (etype1))) || ( SPEC_USIGN (etype2) - && (getSize (etype2) >= getSize (reType)))) + && (getSize (etype2) >= getSize (reType)) + && !(IS_CHAR (etype2) && IS_LITERAL (etype2)))) && !IS_FLOAT (reType)) SPEC_USIGN (reType) = 1; else diff --git a/src/SDCCval.c b/src/SDCCval.c index 6d1e5cc9..0020b56c 100644 --- a/src/SDCCval.c +++ b/src/SDCCval.c @@ -119,7 +119,7 @@ convertIListToConstList(initList *src, literalList **lList) return FALSE; } - if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node)))) + if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node), RESULT_CHECK))) { return FALSE; } @@ -275,7 +275,7 @@ resolveIvalSym (initList * ilist) return; if (ilist->type == INIT_NODE) - ilist->init.node = decorateType (resolveSymbols (ilist->init.node)); + ilist->init.node = decorateType (resolveSymbols (ilist->init.node), RESULT_CHECK); if (ilist->type == INIT_DEEP) resolveIvalSym (ilist->init.deep); @@ -389,18 +389,17 @@ static value *cheapestVal (value *val) !SPEC_USIGN(val->type) && !SPEC_LONG(val->type) && SPEC_CVAL(val->type).v_int >= -128 && - SPEC_CVAL(val->type).v_int <= 127) + SPEC_CVAL(val->type).v_int < 0) { SPEC_NOUN(val->type) = V_CHAR; } - /* this could be too aggressive: - 'unsigned char' promotes to 'signed int', so that we can + /* 'unsigned char' promotes to 'signed int', so that we can reduce it the other way */ if (IS_INT(val->type) && !SPEC_USIGN(val->type) && !SPEC_LONG(val->type) && - SPEC_CVAL(val->type).v_int >= 128 && + SPEC_CVAL(val->type).v_int >= 0 && SPEC_CVAL(val->type).v_int <= 255) { @@ -526,19 +525,8 @@ value *constVal (char *s) the programer wants */ SPEC_NOUN (val->type) = V_INT; } - else if (dval>0x7f && !SPEC_USIGN (val->type)) { // check if we have to promote to int -#if 0 - if ((hex || octal) && /* hex or octal constants may be stored in unsigned type */ - dval<=0xff) { - SPEC_USIGN (val->type) = 1; - } else { - SPEC_NOUN (val->type) = V_INT; - } -#else - /* this is quite agressive: 'unsigned char' will be promoted to 'signed int', - so that the signedness of a char shouldn't matter */ + else { /* store char's always as unsigned; this helps other optimizations */ SPEC_USIGN (val->type) = 1; -#endif } if (dval>0xffff && SPEC_USIGN (val->type)) { // check if we have to promote to long SPEC_LONG (val->type) = 1; @@ -1267,7 +1255,7 @@ valMinus (value * lval, value * rval) SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype, rval->etype, - FALSE)); + TRUE)); if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval); else if (SPEC_LONG (val->type)) @@ -1455,9 +1443,9 @@ valBitwise (value * lval, value * rval, int op) /* create a new value */ val = newValue (); - val->type = copyLinkChain (getSize(rval->type) > getSize(lval->type) ? - rval->type : lval->type); + val->type = computeType (lval->etype, rval->etype, FALSE); val->etype = getSpec (val->type); + SPEC_SCLS (val->etype) = S_LITERAL; switch (op) { @@ -1465,19 +1453,19 @@ valBitwise (value * lval, value * rval, int op) if (SPEC_LONG (val->type)) { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) & - (unsigned long) floatFromVal (rval); + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) & + (TYPE_UDWORD) floatFromVal (rval); else - SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) & - (long) floatFromVal (rval); + SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) & + (TYPE_DWORD) floatFromVal (rval); } else { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) & - (unsigned) floatFromVal (rval); + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) & + (TYPE_UWORD) floatFromVal (rval); else - SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) & (int) floatFromVal (rval); + SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) & (TYPE_WORD) floatFromVal (rval); } break; @@ -1485,20 +1473,20 @@ valBitwise (value * lval, value * rval, int op) if (SPEC_LONG (val->type)) { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) | - (unsigned long) floatFromVal (rval); + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) | + (TYPE_UDWORD) floatFromVal (rval); else - SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) | - (long) floatFromVal (rval); + SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) | + (TYPE_DWORD) floatFromVal (rval); } else { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) | - (unsigned) floatFromVal (rval); + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) | + (TYPE_UWORD) floatFromVal (rval); else SPEC_CVAL (val->type).v_int = - (int) floatFromVal (lval) | (int) floatFromVal (rval); + (TYPE_WORD) floatFromVal (lval) | (TYPE_WORD) floatFromVal (rval); } break; @@ -1507,24 +1495,24 @@ valBitwise (value * lval, value * rval, int op) if (SPEC_LONG (val->type)) { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) ^ - (unsigned long) floatFromVal (rval); + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) ^ + (TYPE_UDWORD) floatFromVal (rval); else - SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) ^ - (long) floatFromVal (rval); + SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) ^ + (TYPE_DWORD) floatFromVal (rval); } else { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) ^ - (unsigned) floatFromVal (rval); + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) ^ + (TYPE_UWORD) floatFromVal (rval); else SPEC_CVAL (val->type).v_int = - (int) floatFromVal (lval) ^ (int) floatFromVal (rval); + (TYPE_WORD) floatFromVal (lval) ^ (TYPE_WORD) floatFromVal (rval); } break; } - + return cheapestVal(val); } @@ -1541,7 +1529,7 @@ valLogicAndOr (value * lval, value * rval, int op) val->type = val->etype = newCharLink (); val->type->class = SPECIFIER; SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */ - SPEC_USIGN (val->type) = 0; + SPEC_USIGN (val->type) = 1; switch (op) { diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 20ad91eb..c3a96b8d 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -4334,7 +4334,8 @@ genCmpGt (iCode * ic, iCode * ifx) letype = getSpec (operandType (left)); retype = getSpec (operandType (right)); - sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); + sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) || + (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype)))); /* assign the amsops */ aopOp (left, ic, FALSE); aopOp (right, ic, FALSE); @@ -4363,8 +4364,8 @@ genCmpLt (iCode * ic, iCode * ifx) letype = getSpec (operandType (left)); retype = getSpec (operandType (right)); - sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - + sign = !((SPEC_USIGN (letype) && !(IS_CHAR (letype) && IS_LITERAL (letype))) || + (SPEC_USIGN (retype) && !(IS_CHAR (retype) && IS_LITERAL (retype)))); /* assign the amsops */ aopOp (left, ic, FALSE); aopOp (right, ic, FALSE); diff --git a/src/pic/glue.c b/src/pic/glue.c index 654d9c33..dbedaff6 100644 --- a/src/pic/glue.c +++ b/src/pic/glue.c @@ -212,7 +212,7 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag) ival = initAggregates (sym, sym->ival, NULL); else ival = newNode ('=', newAst_VALUE(symbolVal (sym)), - decorateType (resolveSymbols (list2expr (sym->ival)))); + decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK)); codeOutFile = statsg->oFile; GcurMemmap = statsg; eBBlockFromiCode (iCodeFromAst (ival)); diff --git a/src/pic16/glue.c b/src/pic16/glue.c index f02dd928..1a6cf051 100644 --- a/src/pic16/glue.c +++ b/src/pic16/glue.c @@ -240,7 +240,7 @@ pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag) ival = initAggregates (sym, sym->ival, NULL); else ival = newNode ('=', newAst_VALUE(symbolVal (sym)), - decorateType (resolveSymbols (list2expr (sym->ival)))); + decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_CHECK)); codeOutFile = statsg->oFile; GcurMemmap = statsg; eBBlockFromiCode (iCodeFromAst (ival)); -- 2.39.5