From 909e288720dc2362fdce0ef27f6780dff3e49c81 Mon Sep 17 00:00:00 2001 From: bernhardheld Date: Wed, 13 Aug 2003 20:10:57 +0000 Subject: [PATCH] * src/SDCCcse.c (algebraicOpts): fix bug converting op from value to type * src/SDCCicode.c (operandOperation): rewritten some ops (*, ==, unary_minus) to fix possible overflows and to accord with ANSI * src/SDCCsymt.c (computeType): literals are handled the same way as any other type * src/SDCCval.c (cheapestVal): removed, it doesn't accord with ANSI (can be re-activated by defining REDUCE_LITERALS) * src/SDCCval.c (constVal): fixed; hex and octal constants can be unsigned, but are signed by default * src/SDCCval.c (constVal): rearranged * src/SDCCval.c (valMod): preliminary fix * src/SDCCval.c (valCastLiteral): use TYPE_* types * support/regression/literalop.c: added, work in progress git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2825 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 18 ++- src/SDCCcse.c | 36 +++--- src/SDCCicode.c | 96 ++++++++++++--- src/SDCCsymt.c | 8 +- src/SDCCval.c | 170 +++++++++++++++++---------- support/regression/tests/literalop.c | 126 ++++++++++++++++++++ 6 files changed, 350 insertions(+), 104 deletions(-) create mode 100644 support/regression/tests/literalop.c diff --git a/ChangeLog b/ChangeLog index b1fb8c30..cb3c009f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2003-08-13 Bernhard Held + + * src/SDCCcse.c (algebraicOpts): fix bug converting op from value to type + * src/SDCCicode.c (operandOperation): rewritten some ops + (*, ==, unary_minus) to fix possible overflows and to accord with ANSI + * src/SDCCsymt.c (computeType): literals are handled the same way as any + other type + * src/SDCCval.c (cheapestVal): removed, it doesn't accord with ANSI (can + be re-activated by defining REDUCE_LITERALS) + * src/SDCCval.c (constVal): fixed; hex and octal constants can be + unsigned, but are signed by default + * src/SDCCval.c (constVal): rearranged + * src/SDCCval.c (valMod): preliminary fix + * src/SDCCval.c (valCastLiteral): use TYPE_* types + * support/regression/literalop.c: added, work in progress + 2003-08-12 Erik Petrich Generate warnings for useless declarations like "char data;" @@ -9,7 +25,7 @@ 2003-08-09 Bernhard Held - * src/SDCCval.c (valMult): fixex overflow detection of negativ int + * src/SDCCval.c (valMult): fix overflow detection of negative int 2003-08-07 Erik Petrich diff --git a/src/SDCCcse.c b/src/SDCCcse.c index 32badbcc..3c9c205c 100644 --- a/src/SDCCcse.c +++ b/src/SDCCcse.c @@ -83,8 +83,8 @@ pcseDef (void *item, va_list ap) void ReplaceOpWithCheaperOp(operand **op, operand *cop) { #ifdef RANGEHUNT - printf ("ReplaceOpWithCheaperOp %s with %s: ", - IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM", + printf ("ReplaceOpWithCheaperOp %s with %s: ", + IS_SYMOP((*op)) ? OP_SYMBOL((*op))->name : "!SYM", IS_SYMOP(cop) ? OP_SYMBOL(cop)->name : "!SYM"); // if op is a register equivalent if (IS_ITEMP(cop) && OP_SYMBOL((*op))->isreqv) { @@ -107,7 +107,7 @@ void ReplaceOpWithCheaperOp(operand **op, operand *cop) { /* replaceAllSymBySym - replaces all operands by operand in an */ /* instruction chain */ /*-----------------------------------------------------------------*/ -void +void replaceAllSymBySym (iCode * ic, operand * from, operand * to, bitVect ** ndpset) { iCode *lic; @@ -325,8 +325,8 @@ DEFSETFUNC (findCheaperOp) IS_ITEMP (IC_RESULT (cdp->diCode))) *opp = IC_RESULT (cdp->diCode); - if ((*opp) && - (isOperandLiteral(*opp) || !checkSign || + if ((*opp) && + (isOperandLiteral(*opp) || !checkSign || (checkSign && IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) && (SPEC_USIGN(operandType (cop))==SPEC_USIGN(operandType (*opp)) && @@ -353,11 +353,11 @@ DEFSETFUNC (findCheaperOp) *opp = operandFromOperand (*opp); (*opp)->isaddr = cop->isaddr; } - + if (IS_SPEC(operandType (cop)) && IS_SPEC(operandType (*opp)) && SPEC_NOUN(operandType(cop)) != SPEC_NOUN(operandType(*opp))) { - // special case: we can make an unsigned char literal + // special case: we can make an unsigned char literal // into an int literal with no cost. if (isOperandLiteral(*opp) && SPEC_NOUN(operandType(*opp)) == V_CHAR @@ -372,9 +372,9 @@ DEFSETFUNC (findCheaperOp) *opp = NULL; return 0; } - + } - + return 1; } @@ -517,7 +517,7 @@ DEFSETFUNC (ifOperandsHave) /*-----------------------------------------------------------------*/ /* ifDefSymIs - if a definition is found in the set */ /*-----------------------------------------------------------------*/ -int +int ifDefSymIs (set * cseSet, operand * sym) { cseDef *loop; @@ -554,7 +554,7 @@ DEFSETFUNC (ifDefSymIsX) /*-----------------------------------------------------------------*/ /* ifDiCodeIs - returns truw if diCode is same */ /*-----------------------------------------------------------------*/ -int +int ifDiCodeIs (set * cseSet, iCode * ic) { cseDef *loop; @@ -825,6 +825,7 @@ algebraicOpts (iCode * ic, eBBlock * ebp) { ic->op = CAST; IC_LEFT (ic)->type = TYPE; + IC_LEFT (ic)->isLiteral = 0; setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic))); } return; @@ -863,6 +864,7 @@ algebraicOpts (iCode * ic, eBBlock * ebp) IC_RIGHT (ic) = IC_LEFT (ic); IC_LEFT (ic) = op; IC_LEFT (ic)->type = TYPE; + IC_LEFT (ic)->isLiteral = 0; setOperandType (IC_LEFT (ic), operandType (IC_RESULT (ic))); } return; @@ -1783,7 +1785,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, /* update the spill location for this */ updateSpillLocation (ic,0); - if (POINTER_SET (ic) && + if (POINTER_SET (ic) && !(IS_BITFIELD (OP_SYMBOL (IC_RESULT (ic))->etype))) { pdop = NULL; @@ -1854,7 +1856,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, change = 1; } } - + /* if left or right changed then do algebraic */ if (!computeOnly && change) { @@ -1889,15 +1891,15 @@ cseBBlock (eBBlock * ebb, int computeOnly, if (pdic && compareType (operandType (IC_RESULT (pdic)), operandType (IC_RESULT (ic))) != 1) pdic = NULL; - if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) + if (pdic && port->cseOk && (*port->cseOk)(ic,pdic) == 0) pdic = NULL; } /* Alternate code */ if (pdic && IS_ITEMP(IC_RESULT(ic))) { if (POINTER_GET(ic) && bitVectBitValue(ebb->ptrsSet,IC_LEFT(ic)->key)) { - /* Mmm, found an equivalent pointer get at a lower level. - This could be a loop however with the same pointer set + /* Mmm, found an equivalent pointer get at a lower level. + This could be a loop however with the same pointer set later on */ } else { /* if previous definition found change this to an assignment */ @@ -1905,7 +1907,7 @@ cseBBlock (eBBlock * ebb, int computeOnly, IC_LEFT(ic) = NULL; IC_RIGHT(ic) = operandFromOperand(IC_RESULT(pdic)); SET_ISADDR(IC_RESULT(ic),0); - SET_ISADDR(IC_RIGHT (ic),0); + SET_ISADDR(IC_RIGHT (ic),0); } } diff --git a/src/SDCCicode.c b/src/SDCCicode.c index d3b62981..eac7ec10 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -121,6 +121,7 @@ iCodeTable codeTable[] = /* checkConstantRange: check a constant against the type */ /*-----------------------------------------------------------------*/ + /* pedantic=0: allmost anything is allowed as long as the absolute value is within the bit range of the type, and -1 is treated as 0xf..f for unsigned types (e.g. in assign) @@ -996,7 +997,7 @@ isOperandOnStack (operand * op) /*-----------------------------------------------------------------*/ /* operandLitValue - literal value of an operand */ /*-----------------------------------------------------------------*/ -double +double operandLitValue (operand * op) { assert (isOperandLiteral (op)); @@ -1030,7 +1031,7 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms) } /*-----------------------------------------------------------------*/ -/* operandOperation - perforoms operations on operands */ +/* operandOperation - performs operations on operands */ /*-----------------------------------------------------------------*/ operand * operandOperation (operand * left, operand * right, @@ -1059,13 +1060,60 @@ operandOperation (operand * left, operand * right, operandLitValue (right))); break; case '*': + /* retval = operandFromValue (valCastLiteral (type, operandLitValue (left) * operandLitValue (right))); - if (!options.lessPedantic && - !IS_FLOAT (OP_VALUE(retval)->type) && - !SPEC_LONG (OP_VALUE(retval)->type)) - ; /* TODO: werror (W_INT_OVL) */ + This could be all we've to do, but with gcc we've to take care about + overflows. Two examples: + ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least + significant bits are lost (52 in fraction, 63 bits would be + necessary to keep full precision). + If the resulting double value is greater than ULONG_MAX (resp. + USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)! + */ + + /* if it is not a specifier then we can assume that */ + /* it will be an unsigned long */ + if (IS_INT (type) || + !IS_SPEC (type)) + { + /* long is handled here, because it can overflow with double */ + if (SPEC_LONG (type) || + !IS_SPEC (type)) + /* signed and unsigned mul are the same, as long as the precision + of the result isn't bigger than the precision of the operands. */ + retval = operandFromValue (valCastLiteral (type, + (TYPE_UDWORD) operandLitValue (left) * + (TYPE_UDWORD) operandLitValue (right))); + else if (SPEC_USIGN (type)) /* unsigned int */ + { + /* unsigned int is handled here in order to detect overflow */ + TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) * + (TYPE_UWORD) operandLitValue (right); + + retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul)); + if (!options.lessPedantic && + ul != (TYPE_UWORD) ul) + werror (W_INT_OVL); + } + else /* int */ + { + /* int is handled here in order to detect overflow */ + TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) * + (TYPE_WORD) operandLitValue (right); + + retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l)); + if (!options.lessPedantic && + l != (TYPE_WORD) l) + werror (W_INT_OVL); + } + } + else + /* all others go here: */ + retval = operandFromValue (valCastLiteral (type, + operandLitValue (left) * + operandLitValue (right))); break; case '/': if ((TYPE_UDWORD) operandLitValue (right) == 0) @@ -1102,7 +1150,7 @@ operandOperation (operand * left, operand * right, retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) << (TYPE_UDWORD) operandLitValue (right)); break; - case RIGHT_OP: { + case RIGHT_OP: /* The number of right shifts is always unsigned. Signed doesn't make sense here. Shifting by a negative number is impossible. */ if (SPEC_USIGN(let)) @@ -1114,10 +1162,23 @@ operandOperation (operand * left, operand * right, retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >> (TYPE_UDWORD) operandLitValue (right)); break; - } case EQ_OP: - retval = operandFromLit (operandLitValue (left) == - operandLitValue (right)); + /* this op doesn't care about signedness */ + { + TYPE_UDWORD l, r; + + l = (TYPE_UDWORD) operandLitValue (left); + if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR) + l &= 0xff; + else if (!SPEC_LONG (OP_VALUE(left)->type)) + l &= 0xffff; + r = (TYPE_UDWORD) operandLitValue (right); + if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR) + r &= 0xff; + else if (!SPEC_LONG (OP_VALUE(right)->type)) + r &= 0xffff; + retval = operandFromLit (l == r); + } break; case '<': retval = operandFromLit (operandLitValue (left) < @@ -1180,7 +1241,8 @@ operandOperation (operand * left, operand * right, break; case UNARYMINUS: - retval = operandFromLit (-1 * operandLitValue (left)); + retval = operandFromValue (valCastLiteral (type, + -1 * operandLitValue (left))); break; case '~': @@ -1204,7 +1266,7 @@ operandOperation (operand * left, operand * right, /*-----------------------------------------------------------------*/ /* isOperandEqual - compares two operand & return 1 if they r = */ /*-----------------------------------------------------------------*/ -int +int isOperandEqual (operand * left, operand * right) { /* if the pointers are equal then they are equal */ @@ -1882,11 +1944,11 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt) /* if the right is a literal & power of 2 */ /* then make it a left shift */ - /* code generated for 1 byte * 1 byte literal = 2 bytes result is more - efficient in most cases than 2 bytes result = 2 bytes << literal + /* code generated for 1 byte * 1 byte literal = 2 bytes result is more + efficient in most cases than 2 bytes result = 2 bytes << literal if port has 1 byte muldiv */ if (p2 && !IS_FLOAT (letype) && - !((resultIsInt) && (getSize (resType) != getSize (ltype)) && + !((resultIsInt) && (getSize (resType) != getSize (ltype)) && (port->support.muldiv == 1))) { if ((resultIsInt) && (getSize (resType) != getSize (ltype))) @@ -2648,7 +2710,7 @@ geniCodeLogic (operand * left, operand * right, int op) check if the literal value is within bounds */ if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype)) { - checkConstantRange(ltype, + checkConstantRange(ltype, OP_VALUE(right), "compare operation", 1); } @@ -3230,7 +3292,7 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree) /*-----------------------------------------------------------------*/ /* geniCodeSwitch - changes a switch to a if statement */ /*-----------------------------------------------------------------*/ -void +void geniCodeSwitch (ast * tree,int lvl) { iCode *ic; diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index c085bc09..7b3b6f58 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -1416,13 +1416,13 @@ computeType (sym_link * type1, sym_link * type2) reType = getSpec (rType); /* if either of them unsigned but not val then make this unsigned */ - if (((!IS_LITERAL(type1) && SPEC_USIGN (etype1)) || - (!IS_LITERAL(type2) && SPEC_USIGN (etype2))) && + if (((/*!IS_LITERAL(type1) &&*/ SPEC_USIGN (etype1)) || + (/*!IS_LITERAL(type2) &&*/ SPEC_USIGN (etype2))) && !IS_FLOAT (reType)) SPEC_USIGN (reType) = 1; else SPEC_USIGN (reType) = 0; - + /* if result is a literal then make not so */ if (IS_LITERAL (reType)) SPEC_SCLS (reType) = S_REGISTER; @@ -1433,7 +1433,7 @@ computeType (sym_link * type1, sym_link * type2) /*--------------------------------------------------------------------*/ /* compareType - will do type check return 1 if match, -1 if castable */ /*--------------------------------------------------------------------*/ -int +int compareType (sym_link * dest, sym_link * src) { if (!dest && !src) diff --git a/src/SDCCval.c b/src/SDCCval.c index 62ffcec2..5d95986e 100644 --- a/src/SDCCval.c +++ b/src/SDCCval.c @@ -228,7 +228,7 @@ copyIlist (initList * src) /*------------------------------------------------------------------*/ /* list2int - converts the first element of the list to value */ /*------------------------------------------------------------------*/ -double +double list2int (initList * val) { initList *i = val; @@ -315,6 +315,7 @@ symbolVal (symbol * sym) return val; } +#if defined(REDUCE_LITERALS) /*--------------------------------------------------------------------*/ /* cheapestVal - convert a val to the cheapest as possible value */ /*--------------------------------------------------------------------*/ @@ -368,6 +369,7 @@ static value *cheapestVal (value *val) { } return val; } +#endif /*-----------------------------------------------------------------*/ /* valueFromLit - creates a value from a literal */ @@ -453,7 +455,6 @@ value *constVal (char *s) unsigned long sval; sscanf (s, scanFmt, &sval); dval=sval; - SPEC_USIGN (val->type) = 1; } else { sscanf (s, scanFmt, &dval); } @@ -482,13 +483,26 @@ value *constVal (char *s) SPEC_NOUN (val->type) = V_INT; } else if (dval>0x7f && !SPEC_USIGN (val->type)) { // check if we have to promote to int - SPEC_NOUN (val->type) = V_INT; + 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; + } } if (dval>0xffff && SPEC_USIGN (val->type)) { // check if we have to promote to long SPEC_LONG (val->type) = 1; } else if (dval>0x7fff && !SPEC_USIGN (val->type)) { // check if we have to promote to long int - SPEC_LONG (val->type) = 1; + if ((hex || octal) && /* hex or octal constants may be stored in unsigned type */ + dval<=0xffff) { + SPEC_USIGN (val->type) = 1; + } else { + SPEC_LONG (val->type) = 1; + if (dval>0x7fffffff) { + SPEC_USIGN (val->type) = 1; + } + } } } @@ -527,7 +541,7 @@ unsigned char hexEscape(char **src) { char *s ; unsigned long value ; - + (*src)++ ; /* Skip over the 'x' */ s = *src ; /* Save for error detection */ @@ -869,7 +883,7 @@ valFromType (sym_link * type) /*------------------------------------------------------------------*/ /* floatFromVal - value to double float conversion */ /*------------------------------------------------------------------*/ -double +double floatFromVal (value * val) { if (!val) @@ -896,7 +910,7 @@ floatFromVal (value * val) else return (double) SPEC_CVAL (val->etype).v_long; } - + if (SPEC_NOUN (val->etype) == V_INT) { if (SPEC_USIGN (val->etype)) return (double) SPEC_CVAL (val->etype).v_uint; @@ -925,7 +939,6 @@ floatFromVal (value * val) return 0; } - /*------------------------------------------------------------------*/ /* valUnaryPM - does the unary +/- operation on a constant */ /*------------------------------------------------------------------*/ @@ -1032,38 +1045,36 @@ valMult (value * lval, value * rval) if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval); - else - { /* signed and unsigned mul are the same, as long as the precision of the result isn't bigger than the precision of the operands. */ - if (SPEC_LONG (val->type)) - SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) * - (TYPE_UDWORD) floatFromVal (rval); - else /* int */ - { - TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) * - (TYPE_UWORD) floatFromVal (rval); - - SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) ul; - if (!options.lessPedantic) - { - if (SPEC_USIGN (val->type)) - { - if (ul != SPEC_CVAL (val->type).v_uint) - werror (W_INT_OVL); - } - else /* signed result */ - { - TYPE_DWORD l = (TYPE_WORD) floatFromVal (lval) * - (TYPE_WORD) floatFromVal (rval); - - if (l != SPEC_CVAL (val->type).v_int) - werror (W_INT_OVL); - } - } - } + else if (SPEC_LONG (val->type)) + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) * + (TYPE_UDWORD) floatFromVal (rval); + else if (SPEC_USIGN (val->type)) /* unsigned */ + { + TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) * + (TYPE_UWORD) floatFromVal (rval); + + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) ul; + if (!options.lessPedantic && + ul != SPEC_CVAL (val->type).v_uint) + werror (W_INT_OVL); + } + else /* int */ + { + TYPE_DWORD l = (TYPE_WORD) floatFromVal (lval) * + (TYPE_WORD) floatFromVal (rval); + + SPEC_CVAL (val->type).v_int = (TYPE_WORD) l; + if (!options.lessPedantic && + l != SPEC_CVAL (val->type).v_int) + werror (W_INT_OVL); } +#ifdef REDUCE_LITERALS return cheapestVal(val); +#else + return val; +#endif } /*------------------------------------------------------------------*/ @@ -1087,7 +1098,7 @@ valDiv (value * lval, value * rval) IS_FLOAT (rval->etype) ? V_FLOAT : V_INT); SPEC_SCLS (val->etype) = S_LITERAL; SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype)); - SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); + SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval); @@ -1096,25 +1107,28 @@ valDiv (value * lval, value * rval) 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); } } } +#ifdef REDUCE_LITERALS return cheapestVal(val); +#else + return val; +#endif } /*------------------------------------------------------------------*/ @@ -1131,29 +1145,33 @@ valMod (value * lval, value * rval) SPEC_NOUN (val->type) = V_INT; /* type is int */ SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */ SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype)); - SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); + SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); 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 = (unsigned long) floatFromVal (lval) % - (unsigned 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 = (unsigned) floatFromVal (lval) % - (unsigned) floatFromVal (rval); + SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) % + (TYPE_WORD) floatFromVal (rval); } } +#ifdef REDUCE_LITERALS return cheapestVal(val); +#else + return val; +#endif } /*------------------------------------------------------------------*/ @@ -1170,11 +1188,11 @@ valPlus (value * lval, value * rval) SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) || IS_FLOAT (rval->etype) ? V_FLOAT : V_INT); SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */ - SPEC_USIGN (val->type) = + SPEC_USIGN (val->type) = SPEC_USIGN (lval->etype) && SPEC_USIGN (rval->etype) && (floatFromVal(lval)+floatFromVal(rval))>=0; - + SPEC_LONG (val->type) = 1; if (IS_FLOAT (val->type)) @@ -1191,7 +1209,11 @@ valPlus (value * lval, value * rval) (long) floatFromVal (rval); } } +#ifdef REDUCE_LITERALS return cheapestVal(val); +#else + return val; +#endif } /*------------------------------------------------------------------*/ @@ -1241,7 +1263,11 @@ valMinus (value * lval, value * rval) } } } +#ifdef REDUCE_LITERALS return cheapestVal(val); +#else + return val; +#endif } /*------------------------------------------------------------------*/ @@ -1271,7 +1297,11 @@ valShift (value * lval, value * rval, int lr) (long) floatFromVal (lval) >> (long) floatFromVal (rval); } +#ifdef REDUCE_LITERALS return cheapestVal(val); +#else + return val; +#endif } /*------------------------------------------------------------------*/ @@ -1401,7 +1431,11 @@ valBitwise (value * lval, value * rval, int op) break; } +#ifdef REDUCE_LITERALS return cheapestVal(val); +#else + return val; +#endif } /*------------------------------------------------------------------*/ @@ -1448,27 +1482,33 @@ valCastLiteral (sym_link * dtype, double fval) val = newValue (); val->etype = getSpec (val->type = copyLinkChain (dtype)); SPEC_SCLS (val->etype) = S_LITERAL; + TYPE_UDWORD l = (TYPE_UDWORD)fval; + /* if it is not a specifier then we can assume that */ /* it will be an unsigned long */ if (!IS_SPEC (val->type)) { - SPEC_CVAL (val->etype).v_ulong = (unsigned long) fval; + SPEC_CVAL (val->etype).v_ulong = l; return val; } if (SPEC_NOUN (val->etype) == V_FLOAT) SPEC_CVAL (val->etype).v_float = fval; - else { - unsigned long l = (unsigned long)fval; + else if (SPEC_NOUN (val->etype) == V_CHAR) { + if (SPEC_USIGN (val->etype)) + SPEC_CVAL (val->etype).v_uint= (TYPE_UBYTE) l; + else + SPEC_CVAL (val->etype).v_int = (TYPE_BYTE) l; + } else { if (SPEC_LONG (val->etype)) { if (SPEC_USIGN (val->etype)) - SPEC_CVAL (val->etype).v_ulong = (unsigned long) l; + SPEC_CVAL (val->etype).v_ulong = (TYPE_UDWORD) l; else - SPEC_CVAL (val->etype).v_long = (long) l; + SPEC_CVAL (val->etype).v_long = (TYPE_DWORD) l; } else { if (SPEC_USIGN (val->etype)) - SPEC_CVAL (val->etype).v_uint = (unsigned short)l; + SPEC_CVAL (val->etype).v_uint = (TYPE_UWORD)l; else - SPEC_CVAL (val->etype).v_int = (short)l; + SPEC_CVAL (val->etype).v_int = (TYPE_WORD)l; } } return val; @@ -1477,7 +1517,7 @@ valCastLiteral (sym_link * dtype, double fval) /*------------------------------------------------------------------*/ /* getNelements - determines # of elements from init list */ /*------------------------------------------------------------------*/ -int +int getNelements (sym_link * type, initList * ilist) { int i; diff --git a/support/regression/tests/literalop.c b/support/regression/tests/literalop.c new file mode 100644 index 00000000..23b42c4f --- /dev/null +++ b/support/regression/tests/literalop.c @@ -0,0 +1,126 @@ +/* Test operandOperation() in SDCCicode.c + + type: char, short, long + */ +#include + +typedef signed {type} stype; +typedef unsigned {type} utype; + +#define _{type} + +#if defined(PORT_HOST) || defined(SDCC_z80) || defined(SDCC_gbz80) +# define idata +# define code +#endif + +volatile char is8 = 8; + +signed char sc; +signed short ss; +signed long sl; +unsigned char uc; +unsigned short us; +unsigned long ul; +volatile signed char vsc; +volatile signed short vss; +volatile signed long vsl; +volatile unsigned char vuc; +volatile unsigned short vus; +volatile unsigned long vul; +stype s; +volatile stype vs; +utype u; +volatile utype vu; + +unsigned long t1, t2; + +void +testOpOp(void) +{ + /* mul ast */ + ASSERT((stype) -3 * (stype) -1 == (stype) 3); + ASSERT((stype) -3 * (stype) 1 == (stype) -3); + ASSERT((stype) 3 * (stype) -1 == (stype) -3); + + ASSERT((stype) 1 * (utype) 0xfffffff7 == (utype) 0xfffffff7); + + ASSERT((unsigned char ) 0xfffffff8 * (unsigned char ) 0xfffffff7 == 0xef48); + ASSERT((unsigned short) 0xfffffff8 * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 0x0048 : 0xffef0048)); + ASSERT((unsigned long ) 0xfffffff8 * (unsigned long ) 0xfffffff7 == 0x0048); + + ASSERT((stype ) 0xfffffff8 * (stype ) 0xfffffff7 == 72); + + ASSERT((signed char ) -1 * (unsigned char ) 0xfffffff7 == (sizeof(int) == 2 ? 0xff09 : 0xffffff09)); + ASSERT((signed short) -1 * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 9u : 0xffff0009)); + ASSERT((signed long ) -1 * (unsigned long ) 0xfffffff7 == 9u); + + ASSERT((signed char ) -2 * (unsigned char ) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffffff8)); + ASSERT((signed short) -2 * (unsigned short) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffefff8)); + ASSERT((signed long ) -2 * (unsigned long ) 0x8004 == 0xfffefff8); + + ASSERT(-1 * 0xfff7 == (sizeof(int) == 2 ? 9 : 0xffff0009)); // 0xfff7 is stored in 'unsigned int' + // but: + ASSERT(-1 * 65527 == -65527); // 65527 (== 0xfff7) is stored in 'signed long' + ASSERT(-1 * 33000 == -33000); + + ASSERT(1 * 10000 * is8 == (sizeof(int) == 2 ? 14464 : 80000)); /* int */ + ASSERT(1 * 10000l * is8 == 80000); /* long */ + ASSERT(1 * 40000u * is8 == (sizeof(int) == 2 ? 57856u : 320000)); /* unsigned */ + ASSERT(1 * 40000 * is8 == 320000); /* long */ + ASSERT(1 * 0x4000 * is8 == (sizeof(int) == 2 ? 0 : 0x20000)); /* unsigned */ + + ASSERT(-1 * 1 < 0); + ASSERT(-1 * 1u > 0); + + + /* mul icode */ + s = -3; + ASSERT(s * (stype) -1 == (stype) 3); + ASSERT(s * (stype) 1 == (stype) -3); + s = 3; + ASSERT(s * (stype) -1 == (stype) -3); + + s = 1; + ASSERT(s * (utype) 0xfffffff7 == (utype) 0xfffffff7); + uc = (unsigned char ) 0xfffffff8; + ASSERT(uc * (unsigned char ) 0xfffffff7 == 0xef48); + us = (unsigned short) 0xfffffff8; + ASSERT(us * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 0x0048 : 0xffef0048)); + ul = (unsigned long ) 0xfffffff8; + ASSERT(ul * (unsigned long ) 0xfffffff7 == 0x0048); + ul = (unsigned long ) 0xfffffff8; + + ASSERT((stype ) 0xfffffff8 * (stype ) 0xfffffff7 == 72); + + ASSERT((signed char ) -1 * (unsigned char ) 0xfffffff7 == (sizeof(int) == 2 ? 0xff09 : 0xffffff09)); + ASSERT((signed short) -1 * (unsigned short) 0xfffffff7 == (sizeof(int) == 2 ? 9u : 0xffff0009)); + ASSERT((signed long ) -1 * (unsigned long ) 0xfffffff7 == 9u); + + ASSERT((signed char ) -2 * (unsigned char ) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffffff8)); + ASSERT((signed short) -2 * (unsigned short) 0x8004 == (sizeof(int) == 2 ? 0xfff8 : 0xfffefff8)); + ASSERT((signed long ) -2 * (unsigned long ) 0x8004 == 0xfffefff8); + + + + ASSERT((stype) -12 / (stype) -3 == (stype) 4); + ASSERT((stype) -12 / (stype) 3 == (stype) -4); + ASSERT((stype) 12 / (stype) -3 == (stype) -4); + +// ASSERT((stype) -12 / (utype) -3 == (stype) 4); +// ASSERT((utype) -12 / (stype) -3 == (stype) 4); +// ASSERT((utype) -12 / (utype) -3 == (stype) 4); + + + ASSERT(12u / 3 * 10000 == 40000); + + ASSERT(-1 / 1 < 0); + + + + ASSERT((stype) -14 % (stype) -3 == (stype) -2); + ASSERT((stype) -14 % (stype) 3 == (stype) -2); + ASSERT((stype) 14 % (stype) -3 == (stype) 2); + + ASSERT(-3 % 2 < 0); +} -- 2.30.2