X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCCval.c;h=6a0095016df7888cb417d2f73b62ae103b09f24d;hb=830f8429290c5ab30fe839957c7f62af51f482c9;hp=6b18f5ea2815b08c7c1d0b3692e0989e3a1d8baf;hpb=40a3694e493bc411b4625ccce7c5804474f7b9af;p=fw%2Fsdcc diff --git a/src/SDCCval.c b/src/SDCCval.c index 6b18f5ea..6a009501 100644 --- a/src/SDCCval.c +++ b/src/SDCCval.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "newalloc.h" int cNestLevel; @@ -103,16 +104,16 @@ 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) @@ -120,7 +121,7 @@ convertIListToConstList(initList *src, literalList **lList) return FALSE; } - if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node), RESULT_CHECK))) + if (!IS_AST_LIT_VALUE(decorateType(resolveSymbols(iLoop->init.node), RESULT_TYPE_NONE))) { return FALSE; } @@ -144,7 +145,7 @@ convertIListToConstList(initList *src, literalList **lList) newL->literalValue = val; newL->count = 1; newL->next = NULL; - + if (last) { last->next = newL; @@ -157,12 +158,12 @@ convertIListToConstList(initList *src, literalList **lList) } iLoop = iLoop->next; } - - if (!head) + + if (!head) { return FALSE; } - + *lList = head; return TRUE; } @@ -171,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; @@ -193,7 +194,7 @@ copyLiteralList(literalList *src) prev = newL; src = src->next; } - + return head; } @@ -333,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)) { @@ -384,7 +385,7 @@ static value *cheapestVal (value *val) { static value *cheapestVal (value *val) { - if (IS_FLOAT (val->type) || IS_CHAR (val->type)) + if (IS_FLOAT (val->type) || IS_FIXED (val->type) || IS_CHAR (val->type)) return val; /* - signed/unsigned must not be changed. @@ -461,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 */ /*-----------------------------------------------------------------*/ @@ -468,8 +492,6 @@ 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 */ @@ -486,74 +508,79 @@ 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; + 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 */ - if (strchr (s, 'l') || strchr (s, 'L')) { - SPEC_NOUN (val->type) = V_INT; - SPEC_LONG (val->type) = 1; - } - /* set the unsigned flag if 'uU' is found */ if (strchr (s, 'u') || strchr (s, 'U')) { SPEC_USIGN (val->type) = 1; } - if (dval<0) { // "-28u" will still be signed and negative - if (dval<-128) { // check if we have to promote to int - SPEC_NOUN (val->type) = V_INT; - } - if (dval<-32768) { // check if we have to promote to long int - SPEC_LONG (val->type) = 1; - } - } else { // >=0 - 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 { /* 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 - if ((hex || octal) && /* hex or octal constants may be stored in unsigned type */ - dval<=0xffff) { + /* 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; + } else { + if (dval<0) { // "-28u" will still be signed and negative + if (dval<-128) { // check if we have to promote to int + SPEC_NOUN (val->type) = V_INT; + } + if (dval<-32768) { // check if we have to promote to long int + SPEC_LONG (val->type) = 1; + } + } else { // >=0 + 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 { /* store char's always as unsigned; this helps other optimizations */ SPEC_USIGN (val->type) = 1; - } else { + } + if (dval>0xffff && SPEC_USIGN (val->type)) { // check if we have to promote to long SPEC_LONG (val->type) = 1; - if (dval>0x7fffffff) { + } + else if (dval>0x7fff && !SPEC_USIGN (val->type)) { // check if we have to promote to long int + 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)) @@ -592,9 +619,9 @@ unsigned char hexEscape(char **src) (*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); @@ -632,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 @@ -644,7 +671,7 @@ unsigned char octalEscape (char **str) { */ -int +int copyStr (char *dest, char *src) { @@ -693,7 +720,7 @@ copyStr (char *dest, char *src) src-- ; break; - case 'x': + case 'x': *dest++ = hexEscape(&src) ; src-- ; break ; @@ -951,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)) @@ -996,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)) @@ -1096,6 +1128,9 @@ valMult (value * lval, value * rval) 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. */ else if (SPEC_LONG (val->type)) @@ -1146,6 +1181,9 @@ valDiv (value * lval, value * rval) 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_USIGN (val->type)) @@ -1219,9 +1257,12 @@ valPlus (value * lval, value * rval) 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_USIGN (val->type)) @@ -1258,9 +1299,12 @@ valMinus (value * lval, value * rval) 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_USIGN (val->type)) @@ -1380,6 +1424,12 @@ valCompare (value * lval, value * rval, int ctype) { 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 */ @@ -1407,6 +1457,12 @@ valCompare (value * lval, value * rval, int ctype) { 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 */ @@ -1513,7 +1569,7 @@ valBitwise (value * lval, value * rval, int op) } break; } - + return cheapestVal(val); } @@ -1560,7 +1616,13 @@ valCastLiteral (sym_link * dtype, double fval) 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 */ @@ -1572,6 +1634,8 @@ valCastLiteral (sym_link * dtype, double fval) if (SPEC_NOUN (val->etype) == V_FLOAT) SPEC_CVAL (val->etype).v_float = 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;