* src/SDCCval.c (checkConstantRange): added
authorbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 4 Jun 2006 20:14:11 +0000 (20:14 +0000)
committerbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 4 Jun 2006 20:14:11 +0000 (20:14 +0000)
* src/SDCCval.h: added checkConstantRange
* support/Util/SDCCerr.c,
* support/Util/SDCCerr.h: replaced unused W_IF_NEVER_TRUE and W_IF_ALWAYS_TRUE by W_COMP_RANGE and W_LIT_OVERFLOW
* src/SDCC.y: moved early 'condition transformations' to SDCCast.c
* src/SDCCast.c (decorateType): added checkConstantRange,
  added 'condition transformations' from SDCC.y so that now W_COMP_RANGE can be emitted with the correct always true/false warning,
  added optimization for double '!';
  result of decorateType() must be assigned back to the tree, because decorateType() can change the tree
* src/SDCCicode.c (geniCodeLogic),
  (geniCodeAssign): replaced new checkConstantRange, added warnings,
  (checkConstantRange): removed, it was only a fragment which never emitted a warning
* src/SDCCsymt.c (computeType): fixed promotion for "-1 < (unsigned bit) b"
* src/pic/ralloc.c (packRegsForAssign),
* src/pic16/ralloc.c (packRegsForAssign),
* src/hc08/ralloc.c (packRegsForAssign),
* src/z80/ralloc.c (packRegsForAssign): ported fix for bug #930931 from mcs51
* src/mcs51/ralloc.c (packRegsForAssign): removed outcommented source
* support/regression/tests/constantRange.c: added
* support/valdiag/tests/constantRange.c: added

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4206 4a8a32a2-be11-0410-ad9d-d568d2c75423

16 files changed:
ChangeLog
src/SDCC.y
src/SDCCast.c
src/SDCCicode.c
src/SDCCsymt.c
src/SDCCval.c
src/SDCCval.h
src/hc08/ralloc.c
src/mcs51/gen.c
src/mcs51/ralloc.c
src/pic/ralloc.c
src/pic16/ralloc.c
src/z80/ralloc.c
support/Util/SDCCerr.c
support/Util/SDCCerr.h
support/valdiag/valdiag.py

index f2ff07e140dc9a0d08f28fced93ee9d1f979e8e8..7491832e12858777aa82a9561450f72a2251d71a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2006-06-04 Bernhard Held <bernhard AT bernhardheld.de>
+
+       * src/SDCCval.c (checkConstantRange): added
+       * src/SDCCval.h: added checkConstantRange
+       * support/Util/SDCCerr.c,
+       * support/Util/SDCCerr.h: replaced unused W_IF_NEVER_TRUE and
+       W_IF_ALWAYS_TRUE by W_COMP_RANGE and W_LIT_OVERFLOW
+       * src/SDCC.y: moved early 'condition transformations' to SDCCast.c
+       * src/SDCCast.c (decorateType): added checkConstantRange,
+       added 'condition transformations' from SDCC.y so that now W_COMP_RANGE
+       can be emitted with the correct always true/false warning,
+       added optimization for double '!';
+       result of decorateType() must be assigned back to the tree, because
+       decorateType() can change the tree
+       * src/SDCCicode.c (geniCodeLogic),
+       (geniCodeAssign): replaced new checkConstantRange, added warnings,
+       (checkConstantRange): removed, it was only a fragment which never
+       emitted a warning
+       * src/SDCCsymt.c (computeType): fixed promotion for
+       "-1 < (unsigned bit) b"
+       * src/pic/ralloc.c (packRegsForAssign),
+       * src/pic16/ralloc.c (packRegsForAssign),
+       * src/hc08/ralloc.c (packRegsForAssign),
+       * src/z80/ralloc.c (packRegsForAssign): ported fix for bug #930931
+       from mcs51
+       * src/mcs51/ralloc.c (packRegsForAssign): removed outcommented source
+       * support/regression/tests/constantRange.c: added
+       * support/valdiag/tests/constantRange.c: added
+
 2006-06-02 Borut Razem <borut.razem AT siol.net>
 
        * support/regression/ports/pic16/support.c: increase stack size
index aae308d1e4db81a653b71fc7b79c9922d7565434..0277e533693135634a81938b05de2409f88be7e5 100644 (file)
@@ -334,40 +334,16 @@ shift_expr
 
 relational_expr
    : shift_expr
-   | relational_expr '<' shift_expr    { 
-       $$ = (port->lt_nge ? 
-             newNode('!',newNode(GE_OP,$1,$3),NULL) :
-             newNode('<', $1,$3));
-   }
-   | relational_expr '>' shift_expr    { 
-          $$ = (port->gt_nle ? 
-                newNode('!',newNode(LE_OP,$1,$3),NULL) :
-                newNode('>',$1,$3));
-   }
-   | relational_expr LE_OP shift_expr  { 
-          $$ = (port->le_ngt ? 
-                newNode('!', newNode('>', $1 , $3 ), NULL) :
-                newNode(LE_OP,$1,$3));
-   }
-   | relational_expr GE_OP shift_expr  { 
-          $$ = (port->ge_nlt ? 
-                newNode('!', newNode('<', $1 , $3 ), NULL) :
-                newNode(GE_OP,$1,$3));
-   }
+   | relational_expr '<' shift_expr   { $$ = newNode('<',  $1,$3);}
+   | relational_expr '>' shift_expr   { $$ = newNode('>',  $1,$3);}
+   | relational_expr LE_OP shift_expr { $$ = newNode(LE_OP,$1,$3);}
+   | relational_expr GE_OP shift_expr { $$ = newNode(GE_OP,$1,$3);}
    ;
 
 equality_expr
    : relational_expr
-   | equality_expr EQ_OP relational_expr  { 
-    $$ = (port->eq_nne ? 
-         newNode('!',newNode(NE_OP,$1,$3),NULL) : 
-         newNode(EQ_OP,$1,$3));
-   }
-   | equality_expr NE_OP relational_expr { 
-       $$ = (port->ne_neq ? 
-            newNode('!', newNode(EQ_OP,$1,$3), NULL) : 
-            newNode(NE_OP,$1,$3));
-   }       
+   | equality_expr EQ_OP relational_expr { $$ = newNode(EQ_OP,$1,$3);}
+   | equality_expr NE_OP relational_expr { $$ = newNode(NE_OP,$1,$3);}
    ;
 
 and_expr
index dc7452705035f00cf057829a4abca9e9da4d7389..c0f85e9ca6208efa9bc75483cc5ae86d100a563e 100644 (file)
@@ -3492,6 +3492,20 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           goto errorTreeReturn;
         }
 
+      /* if left is another '!' */
+      if (tree->left->opval.op == '!')
+        {
+          /* remove double '!!X' by 'X ? 1 : 0' */
+          tree->opval.op = '?';
+          tree->left  = tree->left->left;
+          tree->right = newNode (':',
+                                  newAst_VALUE (constVal ("1")),
+                                  newAst_VALUE (constVal ("0")));
+          tree->right->lineno = tree->lineno;
+          tree->decorated = 0;
+          return decorateType (tree, resultType);
+        }
+
       /* if left is a literal then do it */
       if (IS_LITERAL (LTYPE (tree)))
         {
@@ -3928,36 +3942,56 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               }
         }
 
-      /* if unsigned value < 0  then always false */
+      {
+        CCR_RESULT ccr_result = CCR_OK;
+
+        /* if left is integral and right is literal
+           then check constant range */
+        if (IS_INTEGRAL(LTYPE(tree)) && IS_LITERAL(RTYPE(tree)))
+          ccr_result = checkConstantRange (LTYPE (tree), RTYPE (tree),
+                                           tree->opval.op, FALSE);
+        if (ccr_result == CCR_OK &&
+            IS_INTEGRAL(RTYPE(tree)) && IS_LITERAL(LTYPE(tree)))
+          ccr_result = checkConstantRange (RTYPE (tree), LTYPE (tree),
+                                           tree->opval.op, TRUE);
+        switch (ccr_result)
+            {
+              case CCR_ALWAYS_TRUE:
+              case CCR_ALWAYS_FALSE:
+                if (!options.lessPedantic)
+                  werror (W_COMP_RANGE,
+                          ccr_result == CCR_ALWAYS_TRUE ? "true" : "false");
+                return decorateType (newAst_VALUE (constVal (
+                                   ccr_result == CCR_ALWAYS_TRUE ? "1" : "0")),
+                                                   resultType);
+              case CCR_OK:
+              default:
+                break;
+            }
+      }
+
       /* if (unsigned value) > 0 then '(unsigned value) ? 1 : 0' */
-      if (SPEC_USIGN(LETYPE(tree)) &&
-          !IS_CHAR(LETYPE(tree)) && /* promotion to signed int */
+      if (tree->opval.op == '>' &&
+          SPEC_USIGN(LETYPE(tree)) &&
           IS_LITERAL(RTYPE(tree))  &&
           ((int) floatFromVal (valFromType (RETYPE (tree)))) == 0)
         {
-          if (tree->opval.op == '<')
+          if (resultType == RESULT_TYPE_IFX)
             {
-              return tree->right;
+              /* the parent is an ifx: */
+              /* if (unsigned value) */
+              return tree->left;
             }
-          if (tree->opval.op == '>')
-            {
-              if (resultType == RESULT_TYPE_IFX)
-                {
-                  /* the parent is an ifx: */
-                  /* if (unsigned value) */
-                  return tree->left;
-                }
 
-              /* (unsigned value) ? 1 : 0 */
-              tree->opval.op = '?';
-              tree->right = newNode (':',
-                                     newAst_VALUE (constVal ("1")),
-                                     tree->right); /* val 0 */
-              tree->right->lineno = tree->lineno;
-              tree->right->left->lineno = tree->lineno;
-              tree->decorated = 0;
-              return decorateType (tree, resultType);
-            }
+          /* (unsigned value) ? 1 : 0 */
+          tree->opval.op = '?';
+          tree->right = newNode (':',
+                                  newAst_VALUE (constVal ("1")),
+                                  tree->right); /* val 0 */
+          tree->right->lineno = tree->lineno;
+          tree->right->left->lineno = tree->lineno;
+          tree->decorated = 0;
+          return decorateType (tree, resultType);
         }
 
       /* 'ifx (op == 0)' -> 'ifx (!(op))' */
@@ -3986,6 +4020,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                    tree->opval.val->type);
           return tree;
         }
+
       /* if one is 'signed char ' and the other one is 'unsigned char' */
       /* it's necessary to promote to int */
       if (IS_CHAR (RTYPE (tree)) && IS_CHAR (LTYPE (tree)) &&
@@ -4019,6 +4054,50 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
       LRVAL (tree) = RRVAL (tree) = 1;
       TTYPE (tree) = TETYPE (tree) = newBoolLink ();
+
+      /* condition transformations */
+      {
+        unsigned transformedOp = 0;
+
+        switch (tree->opval.op)
+          {
+            case '<':             /* transform (a < b)  to !(a >= b)  */
+              if (port->lt_nge)
+                transformedOp = GE_OP;
+              break;
+            case '>':             /* transform (a > b)  to !(a <= b)  */
+              if (port->gt_nle)
+                transformedOp = LE_OP;
+              break;
+            case LE_OP:           /* transform (a <= b) to !(a > b)   */
+              if (port->le_ngt)
+                transformedOp = '>';
+              break;
+            case GE_OP:           /* transform (a >= b) to !(a < b)   */
+              if (port->ge_nlt)
+                transformedOp = '<';
+              break;
+            case NE_OP:           /* transform (a != b) to !(a == b)   */
+              if (port->ne_neq)
+                transformedOp = EQ_OP;
+              break;
+            case EQ_OP:           /* transform (a == b) to !(a != b)   */
+              if (port->eq_nne)
+                transformedOp = NE_OP;
+              break;
+            default:
+              break;
+          }
+        if (transformedOp)
+          {
+            tree->opval.op = transformedOp;
+            tree->decorated = 0;
+            tree = newNode ('!', tree, NULL);
+            tree->lineno = tree->left->lineno;
+            return decorateType (tree, resultType);
+          }
+      }
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -4480,9 +4559,12 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*----------------------------*/
     case FOR:
 
-      decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
-      decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
-      decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
+      AST_FOR (tree, initExpr) = decorateType (
+                  resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
+      AST_FOR (tree, condExpr) = decorateType (
+                  resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
+      AST_FOR (tree, loopExpr) = decorateType (
+                  resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
 
       /* if the for loop is reversible then
          reverse it otherwise do what we normally
@@ -4562,6 +4644,15 @@ backPatchLabels (ast * tree, symbol * trueLabel, symbol * falseLabel)
   if (!tree)
     return NULL;
 
+  /* while-loops insert a label between the IFX and the condition,
+     therefore look behind the label too */
+  if (tree->opval.op == LABEL &&
+      IS_ANDORNOT (tree->right))
+    {
+      tree->right = backPatchLabels (tree->right, trueLabel, falseLabel);
+      return tree;
+    }
+
   if (!(IS_ANDORNOT (tree)))
     return tree;
 
index 8ad10a8d9fde7eb0af19fcc3ea4a940009c792e2..30af1cd43f1c7745d73dd45834fe179ad73b9618 100644 (file)
@@ -127,88 +127,6 @@ iCodeTable codeTable[] =
   {SWAP, "swap", picGenericOne, NULL}
 };
 
-/*-----------------------------------------------------------------*/
-/* 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)
-     pedantic=1: -1==-1, not allowed for unsigned types (e.g. in compare)
-     pedantic>1: "char c=200" is not allowed (evaluates to -56)
-*/
-
-void checkConstantRange(sym_link *ltype, value *val, char *msg,
-                        int pedantic) {
-  double max;
-  int warnings=0;
-  int negative=0;
-  long v;
-
-  max = pow ((double)2.0, (double)bitsForType(ltype));
-
-  if (IS_LONG(val->type)) {
-    if (IS_UNSIGNED(val->type)) {
-      v=SPEC_CVAL(val->type).v_ulong;
-    } else {
-      v=SPEC_CVAL(val->type).v_long;
-    }
-  } else {
-    if (IS_UNSIGNED(val->type)) {
-      v=SPEC_CVAL(val->type).v_uint;
-    } else {
-      v=SPEC_CVAL(val->type).v_int;
-    }
-  }
-
-
-#if 0
-  // this could be a good idea
-  if (options.pedantic)
-    pedantic=2;
-#endif
-
-  if (IS_FLOAT(ltype)) {
-    // anything will do
-    return;
-  }
-
-  if (IS_FIXED(ltype)) {
-    // anything will do
-    return;
-  }
-
-  if (!IS_UNSIGNED(val->type) && v<0) {
-    negative=1;
-    if (IS_UNSIGNED(ltype) && (pedantic>1)) {
-      warnings++;
-    }
-    v=-v;
-  }
-
-  // if very pedantic: "char c=200" is not allowed
-  if (pedantic>1 && !IS_UNSIGNED(ltype)) {
-    max = max/2 + negative;
-  }
-
-  if (v >= max) {
-    warnings++;
-  }
-
-#if 0 // temporary disabled, leaving the warning as a reminder
-  if (warnings) {
-    SNPRINTF (message, sizeof(message), "for %s %s in %s",
-             IS_UNSIGNED(ltype) ? "unsigned" : "signed",
-             nounName(ltype), msg);
-    werror (W_CONST_RANGE, message);
-
-    if (pedantic>1)
-      fatalError++;
-  }
-#endif
-}
-
 /*-----------------------------------------------------------------*/
 /* operandName - returns the name of the operand                   */
 /*-----------------------------------------------------------------*/
@@ -3010,8 +2928,17 @@ 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,
-                         OP_VALUE(right), "compare operation", 1);
+      CCR_RESULT ccr_result = checkConstantRange (ltype, rtype, op, FALSE);
+      switch (ccr_result)
+        {
+          case CCR_ALWAYS_TRUE:
+          case CCR_ALWAYS_FALSE:
+            if (!options.lessPedantic)
+              werror (W_COMP_RANGE, "true resp. false");
+            return operandFromLit (ccr_result == CCR_ALWAYS_TRUE ? 1 : 0);
+          default:
+            break;
+        }
     }
 
   /* if one operand is a pointer and the other is a literal generic void pointer,
@@ -3228,10 +3155,11 @@ geniCodeAssign (operand * left, operand * right, int nosupdate, int strictLval)
 
   /* left is integral type and right is literal then
      check if the literal value is within bounds */
-  if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype))
+  if (IS_INTEGRAL (ltype) && right->type == VALUE && IS_LITERAL (rtype) &&
+      checkConstantRange (ltype, rtype, '=', FALSE) == CCR_OVL &&
+      !options.lessPedantic)
     {
-      checkConstantRange(ltype,
-                         OP_VALUE(right), "= operation", 0);
+      werror (W_LIT_OVERFLOW);
     }
 
   /* if the left & right type don't exactly match */
index 40e1fed661ed02d3e1d3172c0342813453db5a8c..9be6c7f5d3f97ca22ffae209848cbcc619b55853 100644 (file)
@@ -1966,12 +1966,12 @@ computeType (sym_link * type1, sym_link * type2,
       && (   (SPEC_USIGN (etype1)
               /* if this operand is promoted to a larger type,
                  then it will be promoted to a signed type */
-              && !(getSize (etype1) < getSize (reType))
+              && !(bitsForType (etype1) < bitsForType (reType))
               /* char require special handling */
               && !IS_CHAR (etype1))
           || /* same for 2nd operand */  
              (SPEC_USIGN (etype2)
-              && !(getSize (etype2) < getSize (reType))
+              && !(bitsForType (etype2) < bitsForType (reType))
               && !IS_CHAR (etype2))
           || /* if both are 'unsigned char' and not promoted
                 let the result be unsigned too */
index e278fb93a901f52777d12df03835ab9f3549ad9c..d8271ba8dc2288a2b52a0fe7d05f998f0bff8b51 100644 (file)
@@ -367,6 +367,258 @@ cheapestVal (value *val)
   return (val);
 }
 
+/*--------------------------------------------------------------------*/
+/* checkConstantRange - check if constant fits in numeric range of    */
+/* var type in comparisons and assignments                            */
+/*--------------------------------------------------------------------*/
+CCR_RESULT
+checkConstantRange (sym_link *var, sym_link *lit, int op, bool exchangeLeftRight)
+{
+  sym_link *reType;
+  double litVal;
+  int varBits;
+
+  litVal = floatFromVal (valFromType (lit));
+  varBits = bitsForType (var);
+
+  /* sanity checks */
+  if (   IS_FLOAT (var)
+      || IS_FIXED (var))
+    return CCR_OK;
+  if (varBits < 1)
+    return CCR_ALWAYS_FALSE;
+  if (varBits > 32)
+    return CCR_ALWAYS_TRUE;
+
+  /* special: assignment */
+  if (op == '=')
+    {
+      if (IS_BIT (var))
+        return CCR_OK;
+
+      if (getenv ("SDCC_VERY_PEDANTIC"))
+        {
+          if (SPEC_USIGN (var))
+            {
+              TYPE_UDWORD maxVal = 0xffffffffu >> (32 - varBits);
+
+              if (   litVal < 0
+                  || litVal > maxVal)
+                return CCR_OVL;
+              return CCR_OK;
+            }
+          else
+            {
+              TYPE_DWORD minVal = 0xffffffff << (varBits - 1);
+              TYPE_DWORD maxVal = 0x7fffffff >> (32 - varBits);
+
+              if (   litVal < minVal
+                  || litVal > maxVal)
+                return CCR_OVL;
+              return CCR_OK;
+            }
+        }
+      else
+        {
+          /* ignore signedness, e.g. allow everything
+             from -127...+255 for (unsigned) char */
+          TYPE_DWORD  minVal = 0xffffffff  << (varBits - 1);
+          TYPE_UDWORD maxVal = 0xffffffffu >> (32 - varBits);
+
+          if (   litVal < minVal
+              || litVal > maxVal)
+            return CCR_OVL;
+          return CCR_OK;
+        }
+    }
+
+  if (exchangeLeftRight)
+    switch (op)
+      {
+        case EQ_OP:             break;
+        case NE_OP:             break;
+        case '>':   op = '<';   break;
+        case GE_OP: op = LE_OP; break;
+        case '<':   op = '>';   break;
+        case LE_OP: op = GE_OP; break;
+        default:                return CCR_ALWAYS_FALSE;
+      }
+
+  reType = computeType (var, lit, RESULT_TYPE_NONE, op);
+
+  if (SPEC_USIGN (reType))
+    {
+      /* unsigned operation */
+      TYPE_UDWORD minValP, maxValP, minValM, maxValM;
+      TYPE_UDWORD opBitsMask = 0xffffffffu >> (32 - bitsForType (reType));
+
+      if (SPEC_USIGN (lit) && SPEC_USIGN (var))
+        {
+          /* both operands are unsigned, this is easy */
+          minValP = 0;
+          maxValP = 0xffffffffu >> (32 - varBits);
+          /* there's only range, just copy it to 2nd set */
+          minValM = minValP;
+          maxValM = maxValP;
+        }
+      else if (SPEC_USIGN (var))
+        {
+          /* lit is casted from signed to unsigned, e.g.:
+               unsigned u;
+                 u == (char) -17
+              -> u == 0xffef'
+          */
+          minValP = 0;
+          maxValP = 0xffffffffu >> (32 - varBits);
+          /* there's only one range, just copy it to 2nd set */
+          minValM = minValP;
+          maxValM = maxValP;
+
+          /* it's an unsigned operation */
+          if (   IS_CHAR (reType)
+              || IS_INT (reType))
+            {
+              /* make signed literal unsigned and
+                 limit no of bits to size of return type */
+              litVal = (TYPE_UDWORD) litVal & opBitsMask;
+            }
+        }
+      else /* SPEC_USIGN (lit) */
+        {
+          /* var is casted from signed to unsigned, e.g.:
+               signed char c;
+                 c == (unsigned) -17
+              -> c == 0xffef'
+
+             The possible values after casting var
+             split up in two, nonconsecutive ranges:
+
+             minValP =      0;  positive range: 0...127
+             maxValP =   0x7f;
+             minValM = 0xff80;  negative range: -128...-1
+             maxValM = 0xffff;
+          */
+
+          /* positive range */
+          minValP = 0;
+          maxValP = 0x7fffffffu >> (32 - varBits);
+
+          /* negative range */
+          minValM = 0xffffffff  << (varBits - 1);
+          maxValM = 0xffffffffu; /* -1 */
+          /* limit no of bits to size of return type */
+          minValM &= opBitsMask;
+          maxValM &= opBitsMask;
+        }
+
+      switch (op)
+        {
+          case EQ_OP:                   /* var == lit */
+            if (   litVal <= maxValP
+                && litVal >= minValP) /* 0 */
+              return CCR_OK;
+            if (   litVal <= maxValM
+                && litVal >= minValM)
+              return CCR_OK;
+            return CCR_ALWAYS_FALSE;
+          case NE_OP:                   /* var != lit */
+            if (   litVal <= maxValP
+                && litVal >= minValP) /* 0 */
+              return CCR_OK;
+            if (   litVal <= maxValM
+                && litVal >= minValM)
+              return CCR_OK;
+            return CCR_ALWAYS_TRUE;
+          case '>':                     /* var >  lit */
+            if (litVal >= maxValM)
+              return CCR_ALWAYS_FALSE;
+            if (litVal <  minValP) /* 0 */
+              return CCR_ALWAYS_TRUE;
+            return CCR_OK;
+          case GE_OP:                   /* var >= lit */
+            if (litVal >  maxValM)
+              return CCR_ALWAYS_FALSE;
+            if (litVal <= minValP) /* 0 */
+              return CCR_ALWAYS_TRUE;
+            return CCR_OK;
+          case '<':                     /* var <  lit */
+            if (litVal >  maxValM)
+              return CCR_ALWAYS_TRUE;
+            if (litVal <= minValP) /* 0 */
+              return CCR_ALWAYS_FALSE;
+            return CCR_OK;
+          case LE_OP:                   /* var <= lit */
+            if (litVal >= maxValM)
+              return CCR_ALWAYS_TRUE;
+            if (litVal <  minValP) /* 0 */
+              return CCR_ALWAYS_FALSE;
+            return CCR_OK;
+          default:
+            return CCR_ALWAYS_FALSE;
+        }
+    }
+  else
+    {
+      /* signed operation */
+      TYPE_DWORD minVal, maxVal;
+
+      if (SPEC_USIGN (var))
+        {
+          /* unsigned var, but signed operation. This happens
+             when var is promoted to signed int.
+             Set actual min/max values of var. */
+          minVal = 0;
+          maxVal = 0xffffffff >> (32 - varBits);
+        }
+      else
+        {
+          /* signed var */
+          minVal = 0xffffffff << (varBits - 1);
+          maxVal = 0x7fffffff >> (32 - varBits);
+        }
+
+      switch (op)
+        {
+          case EQ_OP:                   /* var == lit */
+            if (   litVal > maxVal
+                || litVal < minVal)
+              return CCR_ALWAYS_FALSE;
+            return CCR_OK;
+          case NE_OP:                   /* var != lit */
+            if (   litVal > maxVal
+                || litVal < minVal)
+              return CCR_ALWAYS_TRUE;
+            return CCR_OK;
+          case '>':                     /* var >  lit */
+            if (litVal >= maxVal)
+              return CCR_ALWAYS_FALSE;
+            if (litVal <  minVal)
+              return CCR_ALWAYS_TRUE;
+            return CCR_OK;
+          case GE_OP:                   /* var >= lit */
+            if (litVal >  maxVal)
+              return CCR_ALWAYS_FALSE;
+            if (litVal <= minVal)
+              return CCR_ALWAYS_TRUE;
+            return CCR_OK;
+          case '<':                     /* var <  lit */
+            if (litVal >  maxVal)
+              return CCR_ALWAYS_TRUE;
+            if (litVal <= minVal)
+              return CCR_ALWAYS_FALSE;
+            return CCR_OK;
+          case LE_OP:                   /* var <= lit */
+            if (litVal >= maxVal)
+              return CCR_ALWAYS_TRUE;
+            if (litVal <  minVal)
+              return CCR_ALWAYS_FALSE;
+            return CCR_OK;
+          default:
+            return CCR_ALWAYS_FALSE;
+        }
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* valueFromLit - creates a value from a literal                   */
 /*-----------------------------------------------------------------*/
index 906bc7e5b603d198ff94c1d72b2b6cf5007c787e..700540286db6c1acc0c0914aaadcf495272dbdc5 100644 (file)
@@ -70,6 +70,16 @@ typedef struct initList
   }
 initList;
 
+/* return values from checkConstantRange */
+typedef enum
+  {
+    CCR_OK,           /* evaluate at runtime */
+    CCR_OVL,
+    CCR_ALWAYS_FALSE,
+    CCR_ALWAYS_TRUE
+  }
+CCR_RESULT;
+
 #define  IS_VARG(x)            (x->vArgs)
 
 /* forward definitions for the symbol table related functions */
@@ -85,6 +95,7 @@ value *charVal (char *);
 value *symbolVal (symbol *);
 void printVal (value *);
 double floatFromVal (value *);
+CCR_RESULT checkConstantRange (sym_link *var, sym_link *lit, int op, bool exchangeOps);
 value *array2Ptr (value *);
 value *valUnaryPM (value *);
 value *valComplement (value *);
index 13a4e2fc8f9a68e55fda5127b0474cc15fbc6341..2c40c925ee4f206d5a715b4582a9200467adb2c1 100644 (file)
@@ -1953,7 +1953,6 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
       return 0;
     }
 
-
   /* if the true symbol is defined in far space or on stack
      then we should not since this will increase register pressure */
 #if 0
@@ -2028,16 +2027,18 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
     return 0;                  /* did not find */
 
   /* if assignment then check that right is not a bit */
-  if (ASSIGNMENT (dic) && !POINTER_SET (dic))
+  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
     {
-      sym_link *etype = operandType (IC_RIGHT (dic));
+      sym_link *etype = operandType (IC_RESULT (dic));
       if (IS_BITFIELD (etype))
         {
           /* if result is a bit too then it's ok */
-         etype = operandType (IC_RESULT (dic));
+          etype = operandType (IC_RESULT (ic));
           if (!IS_BITFIELD (etype))
-           return 0;
-       }
+            {
+              return 0;
+            }
+       }
     }
   /* if the result is on stack or iaccess then it must be
      the same atleast one of the operands */
index ab4433ca75dea8b2aac8dc55df216933d856eaad..ce7dcea473f2d97e5f850d713b431f468ecb6200 100644 (file)
@@ -11662,7 +11662,7 @@ gen51Code (iCode * lic)
         case NE_OP:
 
           /* note these two are xlated by algebraic equivalence
-             during parsing SDCC.y */
+             in decorateType() in SDCCast.c */
           werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
                   "got '>=' or '<=' shouldn't have come here");
           break;
index 82ff7c8dc70c3ae045f188f36262a9e536ddd417..972925da7ebed58b927451155fb6b34eb4dea675 100644 (file)
@@ -2178,20 +2178,7 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
             }
        }
     }
-#if 0
-  /* if assignment then check that right is not a bit */
-  if (ASSIGNMENT (dic) && !POINTER_SET (dic))
-    {
-      sym_link *etype = operandType (IC_RIGHT (dic));
-      if (IS_BITFIELD (etype))
-        {
-          /* if result is a bit too then it's ok */
-          etype = operandType (IC_RESULT (dic));
-          if (!IS_BITFIELD (etype))
-            return 0;
-        }
-    }
-#endif
+
   /* if the result is on stack or iaccess then it must be
      the same atleast one of the operands */
   if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
index 3281321b7524b239859904ea79bd362d1a6cb859..d8b5d8df9a6a0f979f3301a8f847e06f1f39f690 100644 (file)
@@ -3084,6 +3084,19 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
        if (!dic)
                return 0;                       /* did not find */
        
+       /* if assignment then check that right is not a bit */
+       if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+       {
+               sym_link *etype = operandType (IC_RESULT (dic));
+               if (IS_BITFIELD (etype))
+               {
+                       /* if result is a bit too then it's ok */
+                       etype = operandType (IC_RESULT (ic));
+                       if (!IS_BITFIELD (etype))
+                               return 0;
+               }
+       }
+
        /* if the result is on stack or iaccess then it must be
        the same at least one of the operands */
        if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
index d14b83fb623093719b1ab70c089268dbafd8048a..c06b5daa8104ed30c46f34aa37732816b5b9fe75 100644 (file)
@@ -3181,12 +3181,12 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
         * if it fits for pic16, but I leave it here just in case */
 
        /* if assignment then check that right is not a bit */
-       if (ASSIGNMENT (dic) && !POINTER_SET (dic)) {
-         sym_link *etype = operandType (IC_RIGHT (dic));
+       if (ASSIGNMENT (ic) && !POINTER_SET (ic)) {
+         sym_link *etype = operandType (IC_RESULT (dic));
 
                if (IS_BITFIELD (etype)) {
                        /* if result is a bit too then it's ok */
-                       etype = operandType (IC_RESULT (dic));
+                       etype = operandType (IC_RESULT (ic));
                        if (!IS_BITFIELD (etype)) {
                                debugLog(" %d bitfields\n");
                          return 0;
index ca66aa9a051220df8cab5cacc5f01c94fbc61ea6..28a18be19bc4d466cba29e2b3ef5ad42bd9599e5 100644 (file)
@@ -1748,6 +1748,21 @@ packRegsForAssign (iCode * ic, eBBlock * ebp)
   if (!dic)
     return 0;                  /* did not find */
 
+  /* if assignment then check that right is not a bit */
+  if (ASSIGNMENT (ic) && !POINTER_SET (ic))
+    {
+      sym_link *etype = operandType (IC_RESULT (dic));
+      if (IS_BITFIELD (etype))
+        {
+          /* if result is a bit too then it's ok */
+          etype = operandType (IC_RESULT (ic));
+          if (!IS_BITFIELD (etype))
+            {
+              return 0;
+            }
+       }
+    }
+
   /* if the result is on stack or iaccess then it must be
      the same atleast one of the operands */
   if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
index aa804d64c6c4e6db339b80c33bdfba7fa645b4b6..6839b417bde682f632b2dd0904050dd297c2dfc3 100644 (file)
@@ -237,8 +237,8 @@ struct
    "Functions called via pointers must be 'reentrant' to take arguments" },
 { W_DOUBLE_UNSUPPORTED, ERROR_LEVEL_WARNING,
    "type 'double' not supported assuming 'float'" },
-{ W_IF_NEVER_TRUE, ERROR_LEVEL_WARNING,
-   "if-statement condition always false, if-statement not generated" },
+{ W_COMP_RANGE, ERROR_LEVEL_WARNING,
+   "comparison is always %s due to limited range of data type" },
 { W_FUNC_NO_RETURN, ERROR_LEVEL_WARNING,
    "no 'return' statement found for function '%s'" },
 { W_PRE_PROC_WARNING, ERROR_LEVEL_WARNING,
@@ -367,8 +367,8 @@ struct
     "symbol name too long, truncated to %d chars" },
 { W_CAST_STRUCT_PTR,ERROR_LEVEL_WARNING,
          "cast of struct %s * to struct %s * " },
-{ W_IF_ALWAYS_TRUE, ERROR_LEVEL_WARNING,
-    "if-statement condition always true, if-statement not generated" },
+{ W_LIT_OVERFLOW, ERROR_LEVEL_WARNING,
+    "overflow in implicit constant conversion" },
 { E_PARAM_NAME_OMITTED, ERROR_LEVEL_ERROR,
     "in function %s: name omitted for parameter %d" },
 { W_NO_FILE_ARG_IN_C1, ERROR_LEVEL_WARNING,
index 64d1bb6bd8e874231892c6b3377ae767a10622c9..c1e357eeab9aca42f56afe46b4e0864ef1df6085 100644 (file)
@@ -109,7 +109,7 @@ SDCCERR - SDCC Standard error handler
 #define E_EXTERN_MISMATCH              91 /* extern declaration mismatches */
 #define W_NONRENT_ARGS                 92 /* fptr non reentrant has args */
 #define W_DOUBLE_UNSUPPORTED           93 /* 'double' not supported yet */
-#define W_IF_NEVER_TRUE                94 /* if always false     */
+#define W_COMP_RANGE                   94 /* comparison is always %s due to limited range of data type */
 #define W_FUNC_NO_RETURN               95 /* no return statement found */
 #define W_PRE_PROC_WARNING             96 /* preprocessor generated warning */
 #define W_STRUCT_AS_ARG                97 /* structure passed as argument */
@@ -173,7 +173,7 @@ SDCCERR - SDCC Standard error handler
 #define W_PTR2INTEGRAL_NOCAST         155
 #define W_SYMBOL_NAME_TOO_LONG        156
 #define W_CAST_STRUCT_PTR             157 /* pointer to different structure types */
-#define W_IF_ALWAYS_TRUE              158
+#define W_LIT_OVERFLOW                158 /* overflow in implicit constant conversion */
 #define E_PARAM_NAME_OMITTED          159
 #define W_NO_FILE_ARG_IN_C1           160
 #define E_NEED_OPT_O_IN_C1            161
index 0cf03703fe788b1ed5487bdf9000d6eecdc17fca..370b8b8112168a57754b33ddba4cdd2dde95bfd2 100644 (file)
@@ -28,7 +28,7 @@ macrodefs = {}
 
 gcc = {
     "CC":"gcc",
-    "CCFLAGS":"-c -Wall",
+    "CCFLAGS":"-c -Wall -DPORT_HOST=1",
     "CCDEF":"-D",
     "CCOUTPUT":"-o",
     "defined": {