X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCval.c;h=7c0e04da24e3f947e5fb44325a9c6fa01feeacfc;hb=808f5e7fbf3de6ae5c1effcdf2764fb6d706b1cf;hp=fdb2c4be0a491999e3aedde062033bc193951a18;hpb=5fed4a0d90d3cdabd0b98a38dd966b327f87a3e7;p=fw%2Fsdcc diff --git a/src/SDCCval.c b/src/SDCCval.c index fdb2c4be..7c0e04da 100644 --- a/src/SDCCval.c +++ b/src/SDCCval.c @@ -268,7 +268,7 @@ list2expr (initList * ilist) /*------------------------------------------------------------------*/ /* resolveIvalSym - resolve symbols in initial values */ /*------------------------------------------------------------------*/ -void +void resolveIvalSym (initList * ilist) { if (!ilist) @@ -374,7 +374,7 @@ static value *cheapestVal (value *val) { static value *cheapestVal (value *val) { - /* - signed/unsigned must no be changed. + /* - signed/unsigned must not be changed. - long must not be changed. the only possible reduction is from signed int to signed char, @@ -1088,18 +1088,9 @@ valMult (value * lval, value * rval) IS_FLOAT (rval->etype) ? V_FLOAT : V_INT); SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */ SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); - /* both signed char and unsigned char are promoted to signed int */ - if (IS_CHAR (lval->etype)) - { - SPEC_USIGN (lval->etype) = 0; - SPEC_NOUN (lval->etype) = V_INT; - } - if (IS_CHAR (rval->etype)) - { - SPEC_USIGN (rval->etype) = 0; - SPEC_NOUN (rval->etype) = V_INT; - } - SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype)); + SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype, + rval->etype, + TRUE)); if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval); /* signed and unsigned mul are the same, as long as the precision of the @@ -1107,27 +1098,25 @@ valMult (value * lval, value * rval) 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 */ + else if (SPEC_USIGN (val->type)) /* unsigned int */ { TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) * (TYPE_UWORD) floatFromVal (rval); SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) ul; - if (!options.lessPedantic && - ul != (TYPE_UWORD) ul) + if (ul != (TYPE_UWORD) ul) werror (W_INT_OVL); } - else /* int */ + else /* signed 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 != (TYPE_WORD) l) + if (l != (TYPE_WORD) l) werror (W_INT_OVL); } - return cheapestVal(val); + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1150,45 +1139,32 @@ valDiv (value * lval, value * rval) SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) || IS_FLOAT (rval->etype) ? V_FLOAT : V_INT); SPEC_SCLS (val->etype) = S_LITERAL; - /* both signed char and unsigned char are promoted to signed int */ - if (IS_CHAR (lval->etype)) - { - SPEC_USIGN (lval->etype) = 0; - SPEC_NOUN (lval->etype) = V_INT; - } - if (IS_CHAR (rval->etype)) - { - SPEC_USIGN (rval->etype) = 0; - SPEC_NOUN (rval->etype) = V_INT; - } - 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_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype, + rval->etype, + TRUE)); if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval); + else if (SPEC_LONG (val->type)) + { + if (SPEC_USIGN (val->type)) + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) / + (TYPE_UDWORD) floatFromVal (rval); + else + SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) / + (TYPE_DWORD) floatFromVal (rval); + } else { - if (SPEC_LONG (val->type)) - { - if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) / - (TYPE_UDWORD) floatFromVal (rval); - else - SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) / - (TYPE_DWORD) floatFromVal (rval); - } + if (SPEC_USIGN (val->type)) + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) / + (TYPE_UWORD) floatFromVal (rval); else - { - if (SPEC_USIGN (val->type)) { - SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) / - (TYPE_UWORD) floatFromVal (rval); - } else { - SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) / - (TYPE_WORD) floatFromVal (rval); - } - } + SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) / + (TYPE_WORD) floatFromVal (rval); } - return cheapestVal(val); + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1204,8 +1180,10 @@ valMod (value * lval, value * rval) val->type = val->etype = newLink (SPECIFIER); 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_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype, + rval->etype, + TRUE)); if (SPEC_LONG (val->type)) { @@ -1218,16 +1196,14 @@ valMod (value * lval, value * rval) } else { - if (SPEC_USIGN (val->type)) { - SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) % - (TYPE_UWORD) floatFromVal (rval); - } else { - SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) % - (TYPE_WORD) floatFromVal (rval); - } + if (SPEC_USIGN (val->type)) + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) % + (TYPE_UWORD) floatFromVal (rval); + else + SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) % + (TYPE_WORD) floatFromVal (rval); } - - return cheapestVal(val); + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1245,30 +1221,30 @@ valPlus (value * lval, value * rval) IS_FLOAT (rval->etype) ? V_FLOAT : V_INT); SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */ SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); - /* both signed char and unsigned char are promoted to signed int */ - if (IS_CHAR (lval->etype)) - { - SPEC_USIGN (lval->etype) = 0; - SPEC_NOUN (lval->etype) = V_INT; - } - if (IS_CHAR (rval->etype)) - { - SPEC_USIGN (rval->etype) = 0; - SPEC_NOUN (rval->etype) = V_INT; - } - SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype)); + SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype, + rval->etype, + TRUE)); if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval); + else if (SPEC_LONG (val->type)) + { + if (SPEC_USIGN (val->type)) + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) + + (TYPE_UDWORD) floatFromVal (rval); + else + 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_ulong = (TYPE_UDWORD) floatFromVal (lval) + - (TYPE_UDWORD) floatFromVal (rval); + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) + + (TYPE_UWORD) floatFromVal (rval); else - SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) + - (TYPE_DWORD) floatFromVal (rval); + SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) + + (TYPE_WORD) floatFromVal (rval); } - return cheapestVal(val); + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1286,30 +1262,30 @@ valMinus (value * lval, value * rval) IS_FLOAT (rval->etype) ? V_FLOAT : V_INT); SPEC_SCLS (val->type) = S_LITERAL; /* will remain literal */ SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); - /* both signed char and unsigned char are promoted to signed int */ - if (IS_CHAR (lval->etype)) - { - SPEC_USIGN (lval->etype) = 0; - SPEC_NOUN (lval->etype) = V_INT; - } - if (IS_CHAR (rval->etype)) - { - SPEC_USIGN (rval->etype) = 0; - SPEC_NOUN (rval->etype) = V_INT; - } - SPEC_USIGN (val->type) = (SPEC_USIGN (lval->etype) | SPEC_USIGN (rval->etype)); + SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype, + rval->etype, + FALSE)); if (IS_FLOAT (val->type)) - SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval); - else + SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval); + else if (SPEC_LONG (val->type)) { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) - - (TYPE_UDWORD) floatFromVal (rval); + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) - + (TYPE_UDWORD) floatFromVal (rval); else - SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) - - (TYPE_DWORD) floatFromVal (rval); + SPEC_CVAL (val->type).v_long = (TYPE_DWORD) floatFromVal (lval) - + (TYPE_DWORD) floatFromVal (rval); } - return cheapestVal(val); + else + { + if (SPEC_USIGN (val->type)) + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) floatFromVal (lval) - + (TYPE_UWORD) floatFromVal (rval); + else + SPEC_CVAL (val->type).v_int = (TYPE_WORD) floatFromVal (lval) - + (TYPE_WORD) floatFromVal (rval); + } + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1330,19 +1306,46 @@ valShift (value * lval, value * rval, int lr) SPEC_USIGN (val->type) = SPEC_USIGN (lval->etype); SPEC_LONG (val->type) = SPEC_LONG (lval->etype); - if (SPEC_USIGN (val->type)) + if (getSize (lval->type) * 8 <= (TYPE_UDWORD) floatFromVal (rval) && + /* left shift */ + (lr || + /* right shift and unsigned */ + (!lr && SPEC_USIGN (rval->type)))) { - SPEC_CVAL (val->type).v_ulong = lr ? - (TYPE_UDWORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \ - (TYPE_UDWORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval); + werror (W_SHIFT_CHANGED, (lr ? "left" : "right")); + } + + if (SPEC_LONG (val->type)) + { + if (SPEC_USIGN (val->type)) + { + SPEC_CVAL (val->type).v_ulong = lr ? + (TYPE_UDWORD) floatFromVal (lval) << (TYPE_UWORD) floatFromVal (rval) : \ + (TYPE_UDWORD) floatFromVal (lval) >> (TYPE_UWORD) floatFromVal (rval); + } + else + { + SPEC_CVAL (val->type).v_long = lr ? + (TYPE_DWORD) floatFromVal (lval) << (TYPE_UWORD) floatFromVal (rval) : \ + (TYPE_DWORD) floatFromVal (lval) >> (TYPE_UWORD) floatFromVal (rval); + } } else { - SPEC_CVAL (val->type).v_long = lr ? - (TYPE_DWORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \ - (TYPE_DWORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval); + if (SPEC_USIGN (val->type)) + { + SPEC_CVAL (val->type).v_uint = lr ? + (TYPE_UWORD) floatFromVal (lval) << (TYPE_UWORD) floatFromVal (rval) : \ + (TYPE_UWORD) floatFromVal (lval) >> (TYPE_UWORD) floatFromVal (rval); + } + else + { + SPEC_CVAL (val->type).v_int = lr ? + (TYPE_WORD) floatFromVal (lval) << (TYPE_UWORD) floatFromVal (rval) : \ + (TYPE_WORD) floatFromVal (lval) >> (TYPE_UWORD) floatFromVal (rval); + } } - return cheapestVal(val); + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1391,17 +1394,18 @@ valCompare (value * lval, value * rval, int ctype) TYPE_UDWORD l, r; l = (TYPE_UDWORD) floatFromVal (lval); - if (SPEC_NOUN(lval->type) == V_CHAR) - l &= 0xffff; /* promote to int */ - else if (!SPEC_LONG (lval->type)) - l &= 0xffff; - r = (TYPE_UDWORD) floatFromVal (rval); - if (SPEC_NOUN(rval->type) == V_CHAR) - r &= 0xffff; /* promote to int */ - else if (!SPEC_LONG (rval->type)) - r &= 0xffff; - + /* In order to correctly compare 'signed int' and 'unsigned int' it's + neccessary to strip them to 16 bit. + Literals are reduced to their cheapest type, therefore left and + right might have different types. It's neccessary to find a + common type: int (used for char too) or long */ + if (!IS_LONG (lval->etype) && + !IS_LONG (rval->etype)) + { + r = (TYPE_UWORD) r; + l = (TYPE_UWORD) l; + } SPEC_CVAL (val->type).v_int = l == r; } break; @@ -1417,17 +1421,18 @@ valCompare (value * lval, value * rval, int ctype) TYPE_UDWORD l, r; l = (TYPE_UDWORD) floatFromVal (lval); - if (SPEC_NOUN(lval->type) == V_CHAR) - l &= 0xffff; /* promote to int */ - else if (!SPEC_LONG (lval->type)) - l &= 0xffff; - r = (TYPE_UDWORD) floatFromVal (rval); - if (SPEC_NOUN(rval->type) == V_CHAR) - r &= 0xffff; /* promote to int */ - else if (!SPEC_LONG (rval->type)) - r &= 0xffff; - + /* In order to correctly compare 'signed int' and 'unsigned int' it's + neccessary to strip them to 16 bit. + Literals are reduced to their cheapest type, therefore left and + right might have different types. It's neccessary to find a + common type: int (used for char too) or long */ + if (!IS_LONG (lval->etype) && + !IS_LONG (rval->etype)) + { + r = (TYPE_UWORD) r; + l = (TYPE_UWORD) l; + } SPEC_CVAL (val->type).v_int = l != r; } break;