* src/SDCCcse.c (algebraicOpts): fix bug converting op from value to type
[fw/sdcc] / src / SDCCicode.c
index bc3ccc161b9877f681f4abe5d7f1b3253458b7e6..eac7ec101b03bae495ee0353fc33b12be159b045 100644 (file)
@@ -67,6 +67,7 @@ PRINTFUNC (picIfx);
 PRINTFUNC (picJumpTable);
 PRINTFUNC (picInline);
 PRINTFUNC (picReceive);
+PRINTFUNC (picDummyRead);
 
 iCodeTable codeTable[] =
 {
@@ -113,32 +114,14 @@ iCodeTable codeTable[] =
   {RECEIVE, "recv", picReceive, NULL},
   {SEND, "send", picGenericOne, NULL},
   {ARRAYINIT, "arrayInit", picGenericOne, NULL},
+  {DUMMY_READ_VOLATILE, "dummy = (volatile)", picDummyRead, NULL}
 };
 
-// this makes it more easy to catch bugs
-struct bitVect *OP_DEFS(struct operand *op) {
-  wassert (IS_SYMOP(op));
-  return OP_SYMBOL(op)->defs;
-}
-struct bitVect *OP_DEFS_SET(struct operand *op, struct bitVect *bv) {
-  wassert (IS_SYMOP(op));
-  OP_SYMBOL(op)->defs=bv;
-  return bv;
-}
-struct bitVect *OP_USES(struct operand *op) {
-  wassert (IS_SYMOP(op));
-  return OP_SYMBOL(op)->uses;
-}
-struct bitVect *OP_USES_SET(struct operand *op, struct bitVect *bv) {
-  wassert (IS_SYMOP(op));
-  OP_SYMBOL(op)->uses=bv;
-  return bv;
-}
-
 /*-----------------------------------------------------------------*/
 /* 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)
@@ -146,7 +129,7 @@ struct bitVect *OP_USES_SET(struct operand *op, struct bitVect *bv) {
      pedantic>1: "char c=200" is not allowed (evaluates to -56)
 */
 
-void checkConstantRange(sym_link *ltype, value *val, char *msg, 
+void checkConstantRange(sym_link *ltype, value *val, char *msg,
                        int pedantic) {
   double max;
   int warnings=0;
@@ -200,7 +183,7 @@ void checkConstantRange(sym_link *ltype, value *val, char *msg,
 
 #if 0 // temporary disabled, leaving the warning as a reminder
   if (warnings) {
-    sprintf (message, "for %s %s in %s", 
+    SNPRINTF (message, sizeof(message), "for %s %s in %s", 
             SPEC_USIGN(ltype) ? "unsigned" : "signed",
             nounName(ltype), msg);
     werror (W_CONST_RANGE, message);
@@ -236,7 +219,7 @@ printOperand (operand * op, FILE * file)
       if (SPEC_NOUN (opetype) == V_FLOAT)
        fprintf (file, "%g {", SPEC_CVAL (opetype).v_float);
       else
-       fprintf (file, "0x%x {", (int) floatFromVal (op->operand.valOperand));
+       fprintf (file, "0x%x {", (unsigned) floatFromVal (op->operand.valOperand));
       printTypeChain (operandType (op), file);
       fprintf (file, "}");
       break;
@@ -481,10 +464,18 @@ PRINTFUNC (picReceive)
   fprintf (of, "\n");
 }
 
+PRINTFUNC (picDummyRead)
+{
+  fprintf (of, "\t");
+  fprintf (of, "%s ", s);
+  printOperand (IC_RIGHT (ic), of);
+  fprintf (of, "\n");
+}
+
 /*-----------------------------------------------------------------*/
 /* piCode - prints one iCode                                       */
 /*-----------------------------------------------------------------*/
-int 
+int
 piCode (void *item, FILE * of)
 {
   iCode *ic = item;
@@ -508,7 +499,7 @@ void PICC(iCode *ic)
 /*-----------------------------------------------------------------*/
 /* printiCChain - prints intermediate code for humans              */
 /*-----------------------------------------------------------------*/
-void 
+void
 printiCChain (iCode * icChain, FILE * of)
 {
   iCode *loop;
@@ -520,7 +511,7 @@ printiCChain (iCode * icChain, FILE * of)
     {
       if ((icTab = getTableEntry (loop->op)))
        {
-         fprintf (of, "%s(%d:%d:%d:%d:%d)\t",
+         fprintf (of, "%s(l%d:s%d:k%d:d%d:s%d)\t",
                   loop->filename, loop->lineno,
                   loop->seq, loop->key, loop->depth, loop->supportRtn);
 
@@ -597,7 +588,7 @@ newiCodeLabelGoto (int op, symbol * label)
 
   ic = newiCode (op, NULL, NULL);
   ic->op = op;
-  ic->argLabel.label = label;
+  ic->label = label;
   IC_LEFT (ic) = NULL;
   IC_RIGHT (ic) = NULL;
   IC_RESULT (ic) = NULL;
@@ -613,11 +604,16 @@ newiTemp (char *s)
   symbol *itmp;
 
   if (s)
-    sprintf (buffer, "%s", s);
+  {
+      SNPRINTF (buffer, sizeof(buffer), "%s", s);
+  }
   else
-    sprintf (buffer, "iTemp%d", iTempNum++);
+  {
+      SNPRINTF (buffer, sizeof(buffer), "iTemp%d", iTempNum++);
+  }
+    
   itmp = newSymbol (buffer, 1);
-  strcpy (itmp->rname, itmp->name);
+  strncpyz (itmp->rname, itmp->name, SDCC_NAME_MAX);
   itmp->isitmp = 1;
 
   return itmp;
@@ -636,10 +632,12 @@ newiTempLabel (char *s)
     return itmplbl;
 
   if (s)
-    itmplbl = newSymbol (s, 1);
+    {
+       itmplbl = newSymbol (s, 1);
+    }
   else
     {
-      sprintf (buffer, "iTempLbl%d", iTempLblNum++);
+      SNPRINTF (buffer, sizeof(buffer), "iTempLbl%d", iTempLblNum++);
       itmplbl = newSymbol (buffer, 1);
     }
 
@@ -658,7 +656,7 @@ newiTempPreheaderLabel ()
 {
   symbol *itmplbl;
 
-  sprintf (buffer, "preHeaderLbl%d", iTempLblNum++);
+  SNPRINTF (buffer, sizeof(buffer), "preHeaderLbl%d", iTempLblNum++);
   itmplbl = newSymbol (buffer, 1);
 
   itmplbl->isitmp = 1;
@@ -735,7 +733,7 @@ copyiCode (iCode * ic)
 iCodeTable *
 getTableEntry (int oper)
 {
-  int i;
+  unsigned i;
 
   for (i = 0; i < (sizeof (codeTable) / sizeof (iCodeTable)); i++)
     if (oper == codeTable[i].icode)
@@ -812,6 +810,8 @@ isParameterToCall (value * args, operand * op)
 {
   value *tval = args;
 
+  wassert (IS_SYMOP(op));
+    
   while (tval)
     {
       if (tval->sym &&
@@ -834,7 +834,7 @@ isOperandGlobal (operand * op)
   if (IS_ITEMP (op))
     return 0;
 
-  if (op->type == SYMBOL &&
+  if (IS_SYMOP(op) &&
       (op->operand.symOperand->level == 0 ||
        IS_STATIC (op->operand.symOperand->etype) ||
        IS_EXTERN (op->operand.symOperand->etype))
@@ -857,13 +857,13 @@ isOperandVolatile (operand * op, bool chkTemp)
     return 0;
 
   opetype = getSpec (optype = operandType (op));
-
-  if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))
-    return 1;
-
-  if (IS_VOLATILE (opetype))
-    return 1;
-  return 0;
+    
+  if (IS_PTR (optype) && DCL_PTR_VOLATILE (optype))   
+    return 1;   
+    
+  if (IS_VOLATILE (opetype))   
+    return 1;   
+  return 0; 
 }
 
 /*-----------------------------------------------------------------*/
@@ -997,7 +997,7 @@ isOperandOnStack (operand * op)
 /*-----------------------------------------------------------------*/
 /* operandLitValue - literal value of an operand                   */
 /*-----------------------------------------------------------------*/
-double 
+double
 operandLitValue (operand * op)
 {
   assert (isOperandLiteral (op));
@@ -1031,7 +1031,7 @@ iCode *getBuiltinParms (iCode *ic, int *pcount, operand **parms)
 }
 
 /*-----------------------------------------------------------------*/
-/* operandOperation - perforoms operations on operands             */
+/* operandOperation - performs operations on operands             */
 /*-----------------------------------------------------------------*/
 operand *
 operandOperation (operand * left, operand * right,
@@ -1039,12 +1039,12 @@ operandOperation (operand * left, operand * right,
 {
   sym_link *let , *ret=NULL;
   operand *retval = (operand *) 0;
-  
+
   assert (isOperandLiteral (left));
   let = getSpec(operandType(left));
   if (right) {
     assert (isOperandLiteral (right));
-    ret = getSpec(operandType(left));
+    ret = getSpec(operandType(right));
   }
 
   switch (op)
@@ -1060,12 +1060,63 @@ operandOperation (operand * left, operand * right,
                                                 operandLitValue (right)));
       break;
     case '*':
+      /*
       retval = operandFromValue (valCastLiteral (type,
                                                 operandLitValue (left) *
                                                 operandLitValue (right)));
+      This could be all we've to do, but with gcc we've to take care about
+      overflows. Two examples:
+      ULONG_MAX * ULONG_MAX doesn't fit into a double, some of the least
+      significant bits are lost (52 in fraction, 63 bits would be
+      necessary to keep full precision).
+      If the resulting double value is greater than ULONG_MAX (resp.
+      USHRT_MAX, ...), then 0 will be assigned to v_ulong (resp. u_uint, ...)!
+      */
+
+      /* if it is not a specifier then we can assume that */
+      /* it will be an unsigned long                      */
+      if (IS_INT (type) ||
+          !IS_SPEC (type))
+        {
+         /* long is handled here, because it can overflow with double */
+         if (SPEC_LONG (type) ||
+             !IS_SPEC (type))
+         /* signed and unsigned mul are the same, as long as the precision
+            of the result isn't bigger than the precision of the operands. */
+           retval = operandFromValue (valCastLiteral (type,
+                    (TYPE_UDWORD) operandLitValue (left) *
+                    (TYPE_UDWORD) operandLitValue (right)));
+         else if (SPEC_USIGN (type)) /* unsigned int */
+           {
+             /* unsigned int is handled here in order to detect overflow */
+             TYPE_UDWORD ul = (TYPE_UWORD) operandLitValue (left) *
+                              (TYPE_UWORD) operandLitValue (right);
+
+             retval = operandFromValue (valCastLiteral (type, (TYPE_UWORD) ul));
+             if (!options.lessPedantic &&
+                 ul != (TYPE_UWORD) ul)
+               werror (W_INT_OVL);
+           }
+         else /* int */
+           {
+             /* int is handled here in order to detect overflow */
+             TYPE_DWORD l = (TYPE_WORD) operandLitValue (left) *
+                            (TYPE_WORD) operandLitValue (right);
+
+             retval = operandFromValue (valCastLiteral (type, (TYPE_WORD) l));
+             if (!options.lessPedantic &&
+                 l != (TYPE_WORD) l)
+               werror (W_INT_OVL);
+           }
+       }
+      else
+       /* all others go here: */
+       retval = operandFromValue (valCastLiteral (type,
+                                                  operandLitValue (left) *
+                                                  operandLitValue (right)));
       break;
     case '/':
-      if ((unsigned long) operandLitValue (right) == 0)
+      if ((TYPE_UDWORD) operandLitValue (right) == 0)
        {
          werror (E_DIVIDE_BY_ZERO);
          retval = right;
@@ -1077,51 +1128,57 @@ operandOperation (operand * left, operand * right,
                                                   operandLitValue (right)));
       break;
     case '%':
-      if ((unsigned long) operandLitValue (right) == 0) {
+      if ((TYPE_UDWORD) operandLitValue (right) == 0) {
          werror (E_DIVIDE_BY_ZERO);
          retval = right;
       }
-      else 
-       retval = operandFromLit ((SPEC_USIGN(let) ? 
-                                 (unsigned long) operandLitValue (left) :
-                                 (long) operandLitValue (left)) %
-                                (SPEC_USIGN(ret) ? 
-                                 (unsigned long) operandLitValue (right) :
-                                 (long) operandLitValue (right)));
-
+      else
+        {
+          if (SPEC_USIGN(let) || SPEC_USIGN(ret))
+           /* one of the operands is unsigned */
+           retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) %
+                                    (TYPE_UDWORD) operandLitValue (right));
+         else
+           /* both operands are signed */
+           retval = operandFromLit ((TYPE_DWORD) operandLitValue (left) %
+                                    (TYPE_DWORD) operandLitValue (right));
+        }
       break;
     case LEFT_OP:
-      retval = operandFromLit ((SPEC_USIGN(let) ? 
-                                 (unsigned long) operandLitValue (left) :
-                                 (long) operandLitValue (left)) <<
-                                (SPEC_USIGN(ret) ? 
-                                 (unsigned long) operandLitValue (right) :
-                                 (long) operandLitValue (right)));
+      /* The number of left shifts is always unsigned. Signed doesn't make
+        sense here. Shifting by a negative number is impossible. */
+      retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) <<
+                              (TYPE_UDWORD) operandLitValue (right));
       break;
-    case RIGHT_OP: {
-      double lval = operandLitValue(left), rval = operandLitValue(right);
-      double res=0;
-      switch ((SPEC_USIGN(let) ? 2 : 0) + (SPEC_USIGN(ret) ? 1 : 0)) 
-       {
-       case 0: // left=unsigned right=unsigned
-         res=(unsigned long)lval >> (unsigned long)rval;
-         break;
-       case 1: // left=unsigned right=signed
-         res=(unsigned long)lval >> (signed long)rval;
-         break;
-       case 2: // left=signed right=unsigned
-         res=(signed long)lval >> (unsigned long)rval;
-         break;
-       case 3: // left=signed right=signed
-         res=(signed long)lval >> (signed long)rval;
-         break;
-       }
-      retval = operandFromLit (res);
+    case RIGHT_OP:
+      /* The number of right shifts is always unsigned. Signed doesn't make
+        sense here. Shifting by a negative number is impossible. */
+      if (SPEC_USIGN(let))
+        /* unsigned: logic shift right */
+        retval = operandFromLit ((TYPE_UDWORD) operandLitValue (left) >>
+                                (TYPE_UDWORD) operandLitValue (right));
+      else
+        /* signed: arithmetic shift right */
+        retval = operandFromLit ((TYPE_DWORD ) operandLitValue (left) >>
+                                (TYPE_UDWORD) operandLitValue (right));
       break;
-    }
     case EQ_OP:
-      retval = operandFromLit (operandLitValue (left) ==
-                              operandLitValue (right));
+      /* this op doesn't care about signedness */
+      {
+       TYPE_UDWORD l, r;
+
+       l = (TYPE_UDWORD) operandLitValue (left);
+       if (SPEC_NOUN(OP_VALUE(left)->type) == V_CHAR)
+         l &= 0xff;
+       else if (!SPEC_LONG (OP_VALUE(left)->type))
+         l &= 0xffff;
+       r = (TYPE_UDWORD) operandLitValue (right);
+       if (SPEC_NOUN(OP_VALUE(right)->type) == V_CHAR)
+         r &= 0xff;
+       else if (!SPEC_LONG (OP_VALUE(right)->type))
+         r &= 0xffff;
+       retval = operandFromLit (l == r);
+      }
       break;
     case '<':
       retval = operandFromLit (operandLitValue (left) <
@@ -1144,16 +1201,19 @@ operandOperation (operand * left, operand * right,
                               operandLitValue (right));
       break;
     case BITWISEAND:
-      retval = operandFromLit ((long)operandLitValue(left) & 
-                              (long)operandLitValue(right));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) &
+                                                (TYPE_UDWORD)operandLitValue(right)));
       break;
     case '|':
-      retval = operandFromLit ((long)operandLitValue (left) |
-                              (long)operandLitValue (right));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) |
+                                                (TYPE_UDWORD)operandLitValue(right)));
       break;
     case '^':
-      retval = operandFromLit ((long)operandLitValue (left) ^
-                              (long)operandLitValue (right));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 (TYPE_UDWORD)operandLitValue(left) ^
+                                                (TYPE_UDWORD)operandLitValue(right)));
       break;
     case AND_OP:
       retval = operandFromLit (operandLitValue (left) &&
@@ -1165,7 +1225,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RRC:
       {
-       long i = (long) operandLitValue (left);
+       TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
 
        retval = operandFromLit ((i >> (getSize (operandType (left)) * 8 - 1)) |
                                 (i << 1));
@@ -1173,7 +1233,7 @@ operandOperation (operand * left, operand * right,
       break;
     case RLC:
       {
-       long i = (long) operandLitValue (left);
+       TYPE_UDWORD i = (TYPE_UDWORD) operandLitValue (left);
 
        retval = operandFromLit ((i << (getSize (operandType (left)) * 8 - 1)) |
                                 (i >> 1));
@@ -1181,11 +1241,12 @@ operandOperation (operand * left, operand * right,
       break;
 
     case UNARYMINUS:
-      retval = operandFromLit (-1 * operandLitValue (left));
+      retval = operandFromValue (valCastLiteral (type,
+                                                 -1 * operandLitValue (left)));
       break;
 
     case '~':
-      retval = operandFromLit (~((long) operandLitValue (left)));
+      retval = operandFromLit (~((TYPE_UDWORD) operandLitValue (left)));
       break;
 
     case '!':
@@ -1205,7 +1266,7 @@ operandOperation (operand * left, operand * right,
 /*-----------------------------------------------------------------*/
 /* isOperandEqual - compares two operand & return 1 if they r =    */
 /*-----------------------------------------------------------------*/
-int 
+int
 isOperandEqual (operand * left, operand * right)
 {
   /* if the pointers are equal then they are equal */
@@ -1532,10 +1593,13 @@ operandFromAst (ast * tree,int lvl)
 
     case EX_LINK:
       return operandFromLink (tree->opval.lnk);
-    }
+      break;
 
-  assert (0);
-  /*  Just to keep the comiler happy */
+    default:
+      assert (0);
+    }
+  
+  /*  Just to keep the compiler happy */
   return (operand *) 0;
 }
 
@@ -1880,11 +1944,11 @@ geniCodeMultiply (operand * left, operand * right,int resultIsInt)
 
   /* if the right is a literal & power of 2 */
   /* then make it a left shift              */
-  /* code generated for 1 byte * 1 byte literal = 2 bytes result is more 
-     efficient in most cases than 2 bytes result = 2 bytes << literal 
+  /* code generated for 1 byte * 1 byte literal = 2 bytes result is more
+     efficient in most cases than 2 bytes result = 2 bytes << literal
      if port has 1 byte muldiv */
   if (p2 && !IS_FLOAT (letype) &&
-      !((resultIsInt) && (getSize (resType) != getSize (ltype)) && 
+      !((resultIsInt) && (getSize (resType) != getSize (ltype)) &&
        (port->support.muldiv == 1)))
     {
       if ((resultIsInt) && (getSize (resType) != getSize (ltype)))
@@ -2069,12 +2133,6 @@ geniCodeAdd (operand * left, operand * right, int lvl)
   int isarray = 0;
   LRTYPE;
 
-#if 0
-  /* if left is an array then array access */
-  if (IS_ARRAY (ltype))
-    return geniCodeArray (left, right,lvl);
-#endif
-
   /* if the right side is LITERAL zero */
   /* return the left side              */
   if (IS_LITERAL (retype) && right->isLiteral && !floatFromVal (valFromType (retype)))
@@ -2136,10 +2194,11 @@ aggrToPtr (sym_link * type, bool force)
     return type;
 
   etype = getSpec (type);
-  ptype = newLink ();
+  ptype = newLink (DECLARATOR);
 
   ptype->next = type;
-  /* if the output class is generic */
+
+  /* if the output class is code */
   if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
     DCL_PTR_CONST (ptype) = port->mem.code_ro;
 
@@ -2151,6 +2210,7 @@ aggrToPtr (sym_link * type, bool force)
   /* the variable was volatile then pointer to volatile */
   if (IS_VOLATILE (etype))
     DCL_PTR_VOLATILE (ptype) = 1;
+
   return ptype;
 }
 
@@ -2167,7 +2227,6 @@ geniCodeArray2Ptr (operand * op)
   if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
     DCL_PTR_CONST (optype) = port->mem.code_ro;
 
-
   /* if the variable was declared a constant */
   /* then the pointer points to a constant */
   if (IS_CONSTANT (opetype))
@@ -2176,6 +2235,7 @@ geniCodeArray2Ptr (operand * op)
   /* the variable was volatile then pointer to volatile */
   if (IS_VOLATILE (opetype))
     DCL_PTR_VOLATILE (optype) = 1;
+
   op->isaddr = 0;
   return op;
 }
@@ -2237,6 +2297,8 @@ geniCodeStruct (operand * left, operand * right, bool islval)
   symbol *element = getStructElement (SPEC_STRUCT (etype),
                                      right->operand.symOperand);
 
+  wassert(IS_SYMOP(right));
+    
   /* add the offset */
   ic = newiCode ('+', left, operandFromLit (element->offset));
 
@@ -2457,8 +2519,7 @@ geniCodeAddressOf (operand * op)
 /*  return op; */
 /*     } */
 
-  p = newLink ();
-  p->class = DECLARATOR;
+  p = newLink (DECLARATOR);
 
   /* set the pointer depending on the storage class */
   if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
@@ -2539,16 +2600,19 @@ geniCodeDerefPtr (operand * op,int lvl)
   sym_link *rtype, *retype;
   sym_link *optype = operandType (op);
 
-  /* if this is a pointer then generate the rvalue */
-  if (IS_PTR (optype))
+  // if this is an array then array access
+  if (IS_ARRAY (optype)) {
+    // don't worry, this will be optimized out later
+    return geniCodeArray (op, operandFromLit (0), lvl);
+  }
+
+  // just in case someone screws up
+  wassert (IS_PTR (optype));
+
+  if (IS_TRUE_SYMOP (op))
     {
-      if (IS_TRUE_SYMOP (op))
-       {
-         op->isaddr = 1;
-         op = geniCodeRValue (op, TRUE);
-       }
-      else
-       op = geniCodeRValue (op, TRUE);
+      op->isaddr = 1;
+      op = geniCodeRValue (op, TRUE);
     }
 
   /* now get rid of the pointer part */
@@ -2561,9 +2625,8 @@ geniCodeDerefPtr (operand * op,int lvl)
       retype = getSpec (rtype = copyLinkChain (optype->next));
     }
 
-  /* if this is a pointer then outputclass needs 2b updated */
-  if (IS_PTR (optype))
-    setOClass (optype, retype);
+  /* outputclass needs 2b updated */
+  setOClass (optype, retype);
 
   op->isGptr = IS_GENPTR (optype);
 
@@ -2647,7 +2710,7 @@ geniCodeLogic (operand * left, operand * right, int op)
      check if the literal value is within bounds */
   if (IS_INTEGRAL (ltype) && IS_VALOP (right) && IS_LITERAL (rtype))
     {
-      checkConstantRange(ltype, 
+      checkConstantRange(ltype,
                         OP_VALUE(right), "compare operation", 1);
     }
 
@@ -2888,7 +2951,7 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
          /* assign */
          operand *top = operandFromSymbol (argVals->sym);
          /* clear useDef and other bitVectors */
-         OP_USES_SET ((top), OP_DEFS_SET ((top), OP_SYMBOL(top)->clashes = NULL));
+         OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
          geniCodeAssign (top, pval, 1);
        }
       else
@@ -3148,7 +3211,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
   /* all integer numbers between the maximum & minimum must */
   /* be present , the maximum value should not exceed 255 */
   min = max = (int) floatFromVal (vch = caseVals);
-  sprintf (buffer, "_case_%d_%d",
+  SNPRINTF (buffer, sizeof(buffer), 
+           "_case_%d_%d",
           tree->values.switchVals.swNum,
           min);
   addSet (&labels, newiTempLabel (buffer));
@@ -3161,7 +3225,8 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
     {
       if (((t = (int) floatFromVal (vch)) - max) != 1)
        return 0;
-      sprintf (buffer, "_case_%d_%d",
+      SNPRINTF (buffer, sizeof(buffer), 
+               "_case_%d_%d",
               tree->values.switchVals.swNum,
               t);
       addSet (&labels, newiTempLabel (buffer));
@@ -3177,9 +3242,14 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
     return 0;
 
   if (tree->values.switchVals.swDefault)
-    sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+    }
   else
-    sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+    }
+    
 
   falseLabel = newiTempLabel (buffer);
 
@@ -3222,7 +3292,7 @@ geniCodeJumpTable (operand * cond, value * caseVals, ast * tree)
 /*-----------------------------------------------------------------*/
 /* geniCodeSwitch - changes a switch to a if statement             */
 /*-----------------------------------------------------------------*/
-void 
+void
 geniCodeSwitch (ast * tree,int lvl)
 {
   iCode *ic;
@@ -3242,7 +3312,7 @@ geniCodeSwitch (ast * tree,int lvl)
                                        operandFromValue (caseVals),
                                        EQ_OP);
 
-      sprintf (buffer, "_case_%d_%d",
+      SNPRINTF (buffer, sizeof(buffer), "_case_%d_%d",
               tree->values.switchVals.swNum,
               (int) floatFromVal (caseVals));
       trueLabel = newiTempLabel (buffer);
@@ -3256,9 +3326,13 @@ geniCodeSwitch (ast * tree,int lvl)
 
   /* if default is present then goto break else break */
   if (tree->values.switchVals.swDefault)
-    sprintf (buffer, "_default_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_default_%d", tree->values.switchVals.swNum);
+    }
   else
-    sprintf (buffer, "_swBrk_%d", tree->values.switchVals.swNum);
+    {
+       SNPRINTF (buffer, sizeof(buffer), "_swBrk_%d", tree->values.switchVals.swNum);
+    }
 
   falseLabel = newiTempLabel (buffer);
   geniCodeGoto (falseLabel);
@@ -3542,9 +3616,25 @@ ast2iCode (ast * tree,int lvl)
     case RIGHT_OP:
       return geniCodeRightShift (geniCodeRValue (left, FALSE),
                                 geniCodeRValue (right, FALSE));
-    case CAST:
+    case CAST: 
+#if 0 // this indeed needs a second thought
+      {
+       operand *op;
+       
+       // let's keep this simple: get the rvalue we need
+       op=geniCodeRValue (right, FALSE);
+       // now cast it to whatever we want
+       op=geniCodeCast (operandType(left), op, FALSE);
+       // if this is going to be used as an lvalue, make it so
+       if (tree->lvalue) {
+         op->isaddr=1;
+       }
+       return op;
+      }
+#else // bug #604575, is it a bug ????
       return geniCodeCast (operandType (left),
                           geniCodeRValue (right, FALSE), FALSE);
+#endif
 
     case '~':
     case '!':
@@ -3752,3 +3842,35 @@ iCodeFromAst (ast * tree)
   ast2iCode (tree,0);
   return reverseiCChain ();
 }
+
+static const char *opTypeToStr(OPTYPE op)
+{
+    switch(op)
+    {
+      case SYMBOL: return "symbol";
+      case VALUE: return "value";
+      case TYPE: return "type";
+    }
+    return "undefined type";    
+}
+
+
+operand *validateOpType(operand        *op, 
+                       const char      *macro,
+                       const char      *args,
+                       OPTYPE          type,
+                       const char      *file, 
+                       unsigned        line)
+{    
+    if (op && op->type == type)
+    {
+       return op;
+    }
+    fprintf(stderr, 
+           "Internal error: validateOpType failed in %s(%s) @ %s:%u:"
+           " expected %s, got %s\n",
+           macro, args, file, line, 
+           opTypeToStr(type), op ? opTypeToStr(op->type) : "null op");
+    exit(-1);
+    return op; // never reached, makes compiler happy.
+}