X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCval.c;h=0cb48884ee96fd2ddb0f545ee87bf95ff20e4ccc;hb=4f521de57e68e4c7cdcabe45c001234eb3fb0792;hp=63fac609388aa2d1e7b39e827a1743831e9254a9;hpb=241274a93ff7f0382230e095be7bc21b49411567;p=fw%2Fsdcc diff --git a/src/SDCCval.c b/src/SDCCval.c index 63fac609..0cb48884 100644 --- a/src/SDCCval.c +++ b/src/SDCCval.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "newalloc.h" int cNestLevel; @@ -57,6 +58,7 @@ newiList (int type, void *ilist) nilist->type = type; nilist->lineno = mylineno; + nilist->filename = currFname; switch (type) { @@ -102,37 +104,37 @@ convertIListToConstList(initList *src, literalList **lList) { initList *iLoop; literalList *head, *last, *newL; - + head = last = NULL; - + if (!src || src->type != INIT_DEEP) { - return FALSE; + return FALSE; } - + iLoop = src->init.deep; - + while (iLoop) { if (iLoop->type != INIT_NODE) { return FALSE; } - - if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node)))) + + if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node), RESULT_TYPE_NONE))) { return FALSE; } iLoop = iLoop->next; } - + // We've now established that the initializer list contains only literal values. - + iLoop = src->init.deep; while (iLoop) { double val = AST_LIT_VALUE(iLoop->init.node); - + if (last && last->literalValue == val) { last->count++; @@ -143,7 +145,7 @@ convertIListToConstList(initList *src, literalList **lList) newL->literalValue = val; newL->count = 1; newL->next = NULL; - + if (last) { last->next = newL; @@ -156,12 +158,12 @@ convertIListToConstList(initList *src, literalList **lList) } iLoop = iLoop->next; } - - if (!head) + + if (!head) { return FALSE; } - + *lList = head; return TRUE; } @@ -170,17 +172,17 @@ literalList * copyLiteralList(literalList *src) { literalList *head, *prev, *newL; - + head = prev = NULL; - + while (src) { newL = Safe_alloc(sizeof(literalList)); - + newL->literalValue = src->literalValue; newL->count = src->count; newL->next = NULL; - + if (prev) { prev->next = newL; @@ -192,7 +194,7 @@ copyLiteralList(literalList *src) prev = newL; src = src->next; } - + return head; } @@ -228,7 +230,7 @@ copyIlist (initList * src) /*------------------------------------------------------------------*/ /* list2int - converts the first element of the list to value */ /*------------------------------------------------------------------*/ -double +double list2int (initList * val) { initList *i = val; @@ -268,19 +270,28 @@ list2expr (initList * ilist) /*------------------------------------------------------------------*/ /* resolveIvalSym - resolve symbols in initial values */ /*------------------------------------------------------------------*/ -void -resolveIvalSym (initList * ilist) +void +resolveIvalSym (initList * ilist, sym_link * type) { + RESULT_TYPE resultType; + if (!ilist) return; if (ilist->type == INIT_NODE) - ilist->init.node = decorateType (resolveSymbols (ilist->init.node)); + { + if (IS_PTR (type)) + resultType = RESULT_TYPE_INT; + else + resultType = getResultTypeFromType (getSpec (type)); + ilist->init.node = decorateType (resolveSymbols (ilist->init.node), + resultType); + } if (ilist->type == INIT_DEEP) - resolveIvalSym (ilist->init.deep); + resolveIvalSym (ilist->init.deep, type); - resolveIvalSym (ilist->next); + resolveIvalSym (ilist->next, type); } /*-----------------------------------------------------------------*/ @@ -315,6 +326,7 @@ symbolVal (symbol * sym) return val; } +#if defined(REDUCE_LITERALS) /*--------------------------------------------------------------------*/ /* cheapestVal - convert a val to the cheapest as possible value */ /*--------------------------------------------------------------------*/ @@ -322,7 +334,7 @@ static value *cheapestVal (value *val) { TYPE_DWORD sval=0; TYPE_UDWORD uval=0; - if (IS_FLOAT(val->type) || IS_CHAR(val->type)) + if (IS_FLOAT(val->type) || IS_FIXED(val->type) || IS_CHAR(val->type)) return val; if (SPEC_LONG(val->type)) { @@ -369,6 +381,46 @@ static value *cheapestVal (value *val) { return val; } +#else + +static value *cheapestVal (value *val) +{ + if (IS_FLOAT (val->type) || IS_FIXED (val->type) || IS_CHAR (val->type)) + return val; + + /* - signed/unsigned must not be changed. + - long must not be changed. + + the only possible reduction is from signed int to signed char, + because it's automatically promoted back to signed int. + + a reduction from unsigned int to unsigned char is a bug, + because an _unsigned_ char is promoted to _signed_ int! */ + 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_NOUN(val->type) = V_CHAR; + } + /* '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 >= 0 && + SPEC_CVAL(val->type).v_int <= 255) + + { + SPEC_NOUN(val->type) = V_CHAR; + SPEC_USIGN(val->type) = 1; + } + return (val); +} +#endif + /*-----------------------------------------------------------------*/ /* valueFromLit - creates a value from a literal */ /*-----------------------------------------------------------------*/ @@ -410,6 +462,29 @@ constFloatVal (char *s) return val; } +/*-----------------------------------------------------------------*/ +/* constFixed16x16Val - converts a FIXED16X16 constant to value */ +/*-----------------------------------------------------------------*/ +value * +constFixed16x16Val (char *s) +{ + value *val = newValue (); + double sval; + + if (sscanf (s, "%lf", &sval) != 1) + { + werror (E_INVALID_FLOAT_CONST, s); + return constVal ("0"); + } + + val->type = val->etype = newLink (SPECIFIER); + SPEC_NOUN (val->type) = V_FLOAT; + SPEC_SCLS (val->type) = S_LITERAL; + SPEC_CVAL (val->type).v_fixed16x16 = fixed16x16FromDouble ( sval ); + + return val; +} + /*-----------------------------------------------------------------*/ /* constVal - converts an INTEGER constant into a cheapest value */ /*-----------------------------------------------------------------*/ @@ -417,15 +492,13 @@ value *constVal (char *s) { value *val; short hex = 0, octal = 0; - char scanFmt[10]; - int scI = 0; double dval; val = newValue (); /* alloc space for value */ val->type = val->etype = newLink (SPECIFIER); /* create the spcifier */ SPEC_SCLS (val->type) = S_LITERAL; - // let's start with an unsigned char + // let's start with a signed char SPEC_NOUN (val->type) = V_CHAR; SPEC_USIGN (val->type) = 0; @@ -435,31 +508,21 @@ value *constVal (char *s) if (!hex && *s == '0' && *(s + 1)) octal = 1; - /* create the scan string */ - scanFmt[scI++] = '%'; - - scanFmt[scI++] = 'l'; - - if (octal) - scanFmt[scI++] = 'o'; - else if (hex) - scanFmt[scI++] = 'x'; - else - scanFmt[scI++] = 'f'; - - scanFmt[scI++] = '\0'; - - if (octal || hex) { + errno = 0; + if (hex || octal) { unsigned long sval; - sscanf (s, scanFmt, &sval); + sval = strtoul (s, NULL, 0); dval=sval; - SPEC_USIGN (val->type) = 1; + if (errno) { + dval = 4294967295.0; + werror (W_INVALID_INT_CONST, s, dval); + } } else { - sscanf (s, scanFmt, &dval); + sscanf (s, "%lf", &dval); } /* Setup the flags first */ - /* set the _long flag if 'lL' is found */ + /* set the b_long flag if 'lL' is found */ if (strchr (s, 'l') || strchr (s, 'L')) { SPEC_NOUN (val->type) = V_INT; SPEC_LONG (val->type) = 1; @@ -478,20 +541,46 @@ value *constVal (char *s) SPEC_LONG (val->type) = 1; } } else { // >=0 - if (dval>0xff && SPEC_USIGN (val->type)) { // check if we have to promote to int + if (dval>0xff || /* check if we have to promote to int */ + SPEC_USIGN (val->type)) { /* if it's unsigned, we can't use unsigned + char. After an integral promotion it will + be a signed int; this certainly isn't what + 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 - SPEC_NOUN (val->type) = V_INT; + else { /* store char's always as unsigned; this helps other optimizations */ + SPEC_USIGN (val->type) = 1; } 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; + } + } } } + /* check for out of range */ + if (dval<-2147483648.0) { + dval = -2147483648.0; + werror (W_INVALID_INT_CONST, s, dval); + } + if (dval>2147483647.0 && !SPEC_USIGN (val->type)) { + dval = 2147483647.0; + werror (W_INVALID_INT_CONST, s, dval); + } + if (dval>4294967295.0) { + dval = 4294967295.0; + werror (W_INVALID_INT_CONST, s, dval); + } + if (SPEC_LONG (val->type)) { if (SPEC_USIGN (val->type)) @@ -527,12 +616,12 @@ unsigned char hexEscape(char **src) { char *s ; unsigned long value ; - + (*src)++ ; /* Skip over the 'x' */ s = *src ; /* Save for error detection */ - + value = strtol (*src, src, 16); - + if (s == *src) { // no valid hex found werror(E_INVALID_HEX); @@ -570,9 +659,9 @@ unsigned char octalEscape (char **str) { return value; } -/*! +/*! /fn int copyStr (char *dest, char *src) - + Copies a source string to a dest buffer interpreting escape sequences and special characters @@ -582,7 +671,7 @@ unsigned char octalEscape (char **str) { */ -int +int copyStr (char *dest, char *src) { @@ -631,7 +720,7 @@ copyStr (char *dest, char *src) src-- ; break; - case 'x': + case 'x': *dest++ = hexEscape(&src) ; src-- ; break ; @@ -869,7 +958,7 @@ valFromType (sym_link * type) /*------------------------------------------------------------------*/ /* floatFromVal - value to double float conversion */ /*------------------------------------------------------------------*/ -double +double floatFromVal (value * val) { if (!val) @@ -889,6 +978,9 @@ floatFromVal (value * val) if (SPEC_NOUN (val->etype) == V_FLOAT) return (double) SPEC_CVAL (val->etype).v_float; + if (SPEC_NOUN (val->etype) == V_FIXED16X16) + return (double) doubleFromFixed16x16( SPEC_CVAL (val->etype).v_fixed16x16 ); + if (SPEC_LONG (val->etype)) { if (SPEC_USIGN (val->etype)) @@ -896,7 +988,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 +1017,6 @@ floatFromVal (value * val) return 0; } - /*------------------------------------------------------------------*/ /* valUnaryPM - does the unary +/- operation on a constant */ /*------------------------------------------------------------------*/ @@ -935,6 +1026,8 @@ valUnaryPM (value * val) /* depending on type */ if (SPEC_NOUN (val->etype) == V_FLOAT) SPEC_CVAL (val->etype).v_float = -1.0 * SPEC_CVAL (val->etype).v_float; + if (SPEC_NOUN (val->etype) == V_FIXED16X16) + SPEC_CVAL (val->etype).v_fixed16x16 = -SPEC_CVAL (val->etype).v_fixed16x16; else { if (SPEC_LONG (val->etype)) @@ -983,6 +1076,10 @@ valComplement (value * val) SPEC_CVAL (val->etype).v_uint = ~SPEC_CVAL (val->etype).v_uint; else SPEC_CVAL (val->etype).v_int = ~SPEC_CVAL (val->etype).v_int; + if (SPEC_NOUN(val->etype) == V_CHAR) + if ( SPEC_CVAL(val->etype).v_int < -128 + || SPEC_CVAL(val->etype).v_int > 127) + SPEC_NOUN(val->etype) = V_INT; } // ~(unsigned 3) now really is signed SPEC_USIGN(val->etype)=0; @@ -1023,43 +1120,41 @@ valMult (value * lval, value * rval) /* create a new value */ val = newValue (); - val->type = val->etype = newLink (SPECIFIER); - 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 (lval->etype) | SPEC_USIGN (rval->etype)); - SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); + val->type = val->etype = computeType (lval->etype, + rval->etype, + RESULT_TYPE_INT, + '*'); + SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) * floatFromVal (rval); else - { + if (IS_FIXED16X16 (val->type)) + SPEC_CVAL (val->type).v_fixed16x16 = fixed16x16FromDouble(floatFromVal (lval) * floatFromVal (rval)); /* 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 - { - 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 */ - { - if ((TYPE_DWORD) ul != 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 int */ + { + TYPE_UDWORD ul = (TYPE_UWORD) floatFromVal (lval) * + (TYPE_UWORD) floatFromVal (rval); + + SPEC_CVAL (val->type).v_uint = (TYPE_UWORD) ul; + if (ul != (TYPE_UWORD) ul) + werror (W_INT_OVL); } - return cheapestVal(val); + else /* signed int */ + { + TYPE_DWORD l = (TYPE_WORD) floatFromVal (lval) * + (TYPE_WORD) floatFromVal (rval); + + SPEC_CVAL (val->type).v_int = (TYPE_WORD) l; + if (l != (TYPE_WORD) l) + werror (W_INT_OVL); + } + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1078,39 +1173,36 @@ valDiv (value * lval, value * rval) /* create a new value */ val = newValue (); - val->type = val->etype = newLink(SPECIFIER); - SPEC_NOUN (val->type) = (IS_FLOAT (lval->etype) || - 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)); + val->type = val->etype = computeType (lval->etype, + rval->etype, + RESULT_TYPE_INT, + '/'); + SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval); else + if (IS_FIXED16X16 (val->type)) + SPEC_CVAL (val->type).v_fixed16x16 = fixed16x16FromDouble( floatFromVal (lval) / floatFromVal (rval) ); + else if (SPEC_LONG (val->type)) { - if (SPEC_LONG (val->type)) - { - if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = - (unsigned long) floatFromVal (lval) / - (unsigned long) floatFromVal (rval); - else - SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) / - (long) floatFromVal (rval); - } + if (SPEC_USIGN (val->type)) + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) / + (TYPE_UDWORD) floatFromVal (rval); else - { - if (SPEC_USIGN (val->type)) { - SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) / - (unsigned) floatFromVal (rval); - } else { - SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) / - (int) 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); } /*------------------------------------------------------------------*/ @@ -1122,34 +1214,32 @@ valMod (value * lval, value * rval) value *val; /* create a new value */ - val = newValue (); - 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)); + val = newValue(); + val->type = val->etype = computeType (lval->etype, + rval->etype, + RESULT_TYPE_INT, + '%'); + SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ 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); - } else { - SPEC_CVAL (val->type).v_int = (unsigned) floatFromVal (lval) % - (unsigned) 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); } /*------------------------------------------------------------------*/ @@ -1161,33 +1251,37 @@ valPlus (value * lval, value * rval) value *val; /* create a new value */ - val = newValue (); - val->type = val->etype = newLink (SPECIFIER); - 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 (lval->etype) && - SPEC_USIGN (rval->etype) && - (floatFromVal(lval)+floatFromVal(rval))>=0; - - SPEC_LONG (val->type) = 1; + val = newValue(); + val->type = val->etype = computeType (lval->etype, + rval->etype, + RESULT_TYPE_INT, + '+'); + SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) + floatFromVal (rval); else + if (IS_FIXED16X16 (val->type)) + SPEC_CVAL (val->type).v_fixed16x16 = fixed16x16FromDouble( floatFromVal (lval) + floatFromVal (rval) ); + else if (SPEC_LONG (val->type)) { - if (SPEC_LONG (val->type)) - { - if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = (unsigned long) floatFromVal (lval) + - (unsigned long) floatFromVal (rval); - else - SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) + - (long) floatFromVal (rval); - } + 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); } - 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); } /*------------------------------------------------------------------*/ @@ -1199,45 +1293,37 @@ valMinus (value * lval, value * rval) value *val; /* create a new value */ - val = newValue (); - val->type = val->etype = newLink (SPECIFIER); - 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 (lval->etype) && - SPEC_USIGN (rval->etype) && - (floatFromVal(lval)-floatFromVal(rval))>=0; - - SPEC_LONG (val->type) = (SPEC_LONG (lval->etype) | SPEC_LONG (rval->etype)); + val = newValue(); + val->type = val->etype = computeType (lval->etype, + rval->etype, + RESULT_TYPE_INT, + '-'); + SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ if (IS_FLOAT (val->type)) SPEC_CVAL (val->type).v_float = floatFromVal (lval) - floatFromVal (rval); else + if (IS_FIXED16X16 (val->type)) + SPEC_CVAL (val->type).v_fixed16x16 = fixed16x16FromDouble( floatFromVal (lval) - floatFromVal (rval) ); + else if (SPEC_LONG (val->type)) { - if (SPEC_LONG (val->type)) - { - if (SPEC_USIGN (val->type)) { - SPEC_CVAL (val->type).v_ulong = - (unsigned long) floatFromVal (lval) - - (unsigned long) floatFromVal (rval); - } else { - SPEC_CVAL (val->type).v_long = (long) floatFromVal (lval) - - (long) floatFromVal (rval); - } - } + if (SPEC_USIGN (val->type)) + SPEC_CVAL (val->type).v_ulong = (TYPE_UDWORD) floatFromVal (lval) - + (TYPE_UDWORD) floatFromVal (rval); else - { - if (SPEC_USIGN (val->type)) { - SPEC_CVAL (val->type).v_uint = (unsigned) floatFromVal (lval) - - (unsigned) floatFromVal (rval); - } else { - SPEC_CVAL (val->type).v_int = (int) floatFromVal (lval) - - (int) 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); } /*------------------------------------------------------------------*/ @@ -1249,25 +1335,53 @@ valShift (value * lval, value * rval, int lr) value *val; /* create a new value */ - val = newValue (); - val->type = val->etype = newIntLink (); - 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) = 1; + val = newValue(); + val->type = val->etype = computeType (lval->etype, + NULL, + RESULT_TYPE_INT, + 'S'); + SPEC_SCLS (val->etype) = S_LITERAL; /* will remain literal */ + + if (getSize (val->type) * 8 <= (TYPE_UDWORD) floatFromVal (rval) && + /* left shift */ + (lr || + /* right shift and unsigned */ + (!lr && SPEC_USIGN (rval->type)))) + { + werror (W_SHIFT_CHANGED, (lr ? "left" : "right")); + } if (SPEC_LONG (val->type)) { if (SPEC_USIGN (val->type)) - SPEC_CVAL (val->type).v_ulong = lr ? - (unsigned long) floatFromVal (lval) << (unsigned long) floatFromVal (rval) : \ - (unsigned long) floatFromVal (lval) >> (unsigned long) floatFromVal (rval); + { + SPEC_CVAL (val->type).v_ulong = lr ? + (TYPE_UDWORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \ + (TYPE_UDWORD) floatFromVal (lval) >> (TYPE_UDWORD) 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); + } + } + else + { + if (SPEC_USIGN (val->type)) + { + SPEC_CVAL (val->type).v_uint = lr ? + (TYPE_UWORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \ + (TYPE_UWORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval); + } else - SPEC_CVAL (val->type).v_long = lr ? - (long) floatFromVal (lval) << (long) floatFromVal (rval) : \ - (long) floatFromVal (lval) >> (long) floatFromVal (rval); + { + SPEC_CVAL (val->type).v_int = lr ? + (TYPE_WORD) floatFromVal (lval) << (TYPE_UDWORD) floatFromVal (rval) : \ + (TYPE_WORD) floatFromVal (lval) >> (TYPE_UDWORD) floatFromVal (rval); + } } - - return cheapestVal(val); + return cheapestVal (val); } /*------------------------------------------------------------------*/ @@ -1305,11 +1419,70 @@ valCompare (value * lval, value * rval, int ctype) break; case EQ_OP: - SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval); + if (SPEC_NOUN(lval->type) == V_FLOAT || + SPEC_NOUN(rval->type) == V_FLOAT) + { + SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval); + } + else + if (SPEC_NOUN(lval->type) == V_FIXED16X16 || + SPEC_NOUN(rval->type) == V_FIXED16X16) + { + SPEC_CVAL (val->type).v_int = floatFromVal (lval) == floatFromVal (rval); + } + else + { + /* integrals: ignore signedness */ + TYPE_UDWORD l, r; + + l = (TYPE_UDWORD) floatFromVal (lval); + r = (TYPE_UDWORD) floatFromVal (rval); + /* 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; - case NE_OP: - SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval); + if (SPEC_NOUN(lval->type) == V_FLOAT || + SPEC_NOUN(rval->type) == V_FLOAT) + { + SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval); + } + else + if (SPEC_NOUN(lval->type) == V_FIXED16X16 || + SPEC_NOUN(rval->type) == V_FIXED16X16) + { + SPEC_CVAL (val->type).v_int = floatFromVal (lval) != floatFromVal (rval); + } + else + { + /* integrals: ignore signedness */ + TYPE_UDWORD l, r; + + l = (TYPE_UDWORD) floatFromVal (lval); + r = (TYPE_UDWORD) floatFromVal (rval); + /* 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; } @@ -1327,9 +1500,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, RESULT_TYPE_CHAR, op); val->etype = getSpec (val->type); + SPEC_SCLS (val->etype) = S_LITERAL; switch (op) { @@ -1337,19 +1510,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; @@ -1357,20 +1530,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; @@ -1379,20 +1552,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; } @@ -1413,7 +1586,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) { @@ -1437,34 +1610,54 @@ value * valCastLiteral (sym_link * dtype, double fval) { value *val; + TYPE_UDWORD l = (TYPE_UDWORD)fval; if (!dtype) return NULL; val = newValue (); - val->etype = getSpec (val->type = copyLinkChain (dtype)); + if (dtype) + val->etype = getSpec (val->type = copyLinkChain (dtype)); + else + { + val->etype = val->type = newLink (SPECIFIER); + SPEC_NOUN (val->etype) = V_VOID; + } SPEC_SCLS (val->etype) = S_LITERAL; + /* 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_FIXED16X16) + SPEC_CVAL (val->etype).v_fixed16x16 = fixed16x16FromDouble( fval ); + else if (SPEC_NOUN (val->etype) == V_BIT || + SPEC_NOUN (val->etype) == V_SBIT) + SPEC_CVAL (val->etype).v_uint = l ? 1 : 0; + else if (SPEC_NOUN (val->etype) == V_BITFIELD) + SPEC_CVAL (val->etype).v_uint = l & + (0xffffu >> (16 - SPEC_BLEN (val->etype))); + 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; @@ -1473,7 +1666,7 @@ valCastLiteral (sym_link * dtype, double fval) /*------------------------------------------------------------------*/ /* getNelements - determines # of elements from init list */ /*------------------------------------------------------------------*/ -int +int getNelements (sym_link * type, initList * ilist) { int i; @@ -1559,10 +1752,7 @@ valForArray (ast * arrExpr) val->type = newLink (DECLARATOR); if (SPEC_SCLS (arrExpr->left->etype) == S_CODE) - { - DCL_TYPE (val->type) = CPOINTER; - DCL_PTR_CONST (val->type) = port->mem.code_ro; - } + DCL_TYPE (val->type) = CPOINTER; else if (SPEC_SCLS (arrExpr->left->etype) == S_XDATA) DCL_TYPE (val->type) = FPOINTER; else if (SPEC_SCLS (arrExpr->left->etype) == S_XSTACK) @@ -1573,7 +1763,7 @@ valForArray (ast * arrExpr) DCL_TYPE (val->type) = EEPPOINTER; else DCL_TYPE (val->type) = POINTER; - val->type->next = arrExpr->left->ftype; + val->type->next = arrExpr->left->ftype->next; val->etype = getSpec (val->type); return val; } @@ -1630,10 +1820,7 @@ valForStructElem (ast * structT, ast * elemT) val->type = newLink (DECLARATOR); if (SPEC_SCLS (structT->etype) == S_CODE) - { - DCL_TYPE (val->type) = CPOINTER; - DCL_PTR_CONST (val->type) = port->mem.code_ro; - } + DCL_TYPE (val->type) = CPOINTER; else if (SPEC_SCLS (structT->etype) == S_XDATA) DCL_TYPE (val->type) = FPOINTER; else if (SPEC_SCLS (structT->etype) == S_XSTACK)