* src/SDCCcse.c (algebraicOpts): copy operands before modification
[fw/sdcc] / src / SDCCicode.c
index a3f26e677ac067660253f6058407c220b533bab9..381a2bcb68800c04c9c113714d324b0adfc808ef 100644 (file)
@@ -47,8 +47,8 @@ symbol *entryLabel;           /* function entry  label */
 /* forward definition of some functions */
 operand *geniCodeDivision (operand *, operand *);
 operand *geniCodeAssign (operand *, operand *, int);
-operand *geniCodeArray (operand *, operand *,int);
-operand *geniCodeArray2Ptr (operand *);
+static operand *geniCodeArray (operand *, operand *,int);
+static operand *geniCodeArray2Ptr (operand *);
 operand *geniCodeRValue (operand *, bool);
 operand *geniCodeDerefPtr (operand *,int);
 int isLvaluereq(int lvl);
@@ -1202,8 +1202,9 @@ operandOperation (operand * left, operand * right,
     case LEFT_OP:
       /* 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));
+      retval = operandFromValue (valCastLiteral (type,
+                                ((TYPE_UDWORD) operandLitValue (left) <<
+                                 (TYPE_UDWORD) operandLitValue (right))));
       break;
     case RIGHT_OP:
       /* The number of right shifts is always unsigned. Signed doesn't make
@@ -1532,6 +1533,7 @@ operandFromSymbol (symbol * sym)
          and before liveRange calculation */
       sym->reqv = newiTempOperand (sym->type, 0);
       sym->reqv->key = sym->key;
+      OP_SYMBOL (sym->reqv)->prereqv = sym;
       OP_SYMBOL (sym->reqv)->key = sym->key;
       OP_SYMBOL (sym->reqv)->isreqv = 1;
       OP_SYMBOL (sym->reqv)->islocal = 1;
@@ -1732,6 +1734,7 @@ getArraySizePtr (operand * op)
 /*-----------------------------------------------------------------*/
 /* perform "usual unary conversions"                               */
 /*-----------------------------------------------------------------*/
+#if 0
 static operand *
 usualUnaryConversions (operand * op)
 {
@@ -1745,6 +1748,7 @@ usualUnaryConversions (operand * op)
     }
   return op;
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* perform "usual binary conversions"                              */
@@ -1763,12 +1767,19 @@ usualBinaryConversions (operand ** op1, operand ** op2,
      This if for 'mul a,b', which takes two chars and returns an int */
   if (   isMul
       /* && promoteCharToInt   superfluous, already handled by computeType() */
-      && IS_CHAR (getSpec (ltype))
-      && IS_CHAR (getSpec (rtype))
-      && !(IS_UNSIGNED (getSpec (rtype)) ^ IS_UNSIGNED (getSpec (ltype)))
       && IS_INT  (getSpec (ctype)))
-    return ctype;
+    {
+      sym_link *retype = getSpec (rtype);
+      sym_link *letype = getSpec (ltype);
 
+      if (   IS_CHAR (letype)
+         && IS_CHAR (retype)
+         && IS_UNSIGNED (letype)
+         && IS_UNSIGNED (retype))
+       {
+         return ctype;
+       }
+    }
   *op1 = geniCodeCast (ctype, *op1, TRUE);
   *op2 = geniCodeCast (ctype, *op2, TRUE);
 
@@ -1852,6 +1863,12 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
       return op;
     }
 
+  if (IS_ITEMP (op) && IS_ARRAY (OP_SYMBOL (op)->type))
+    {
+      geniCodeArray2Ptr (op);
+      op->isaddr = 0;
+    }
+    
   /* if the operand is already the desired type then do nothing */
   if (compareType (type, optype) == 1)
     return op;
@@ -1922,6 +1939,14 @@ geniCodeCast (sym_link * type, operand * op, bool implicit)
   }
 
   /* if they are the same size create an assignment */
+  
+  /* This seems very dangerous to me, since there are several */
+  /* optimizations (for example, gcse) that don't notice the  */
+  /* cast hidden in this assignement and may simplify an      */
+  /* iCode to use the original (uncasted) operand.            */
+  /* Unfortunately, other things break when this cast is      */
+  /* made explicit. Need to fix this someday.                 */
+  /* -- EEP, 2004/01/21                                       */
   if (getSize (type) == getSize (optype) &&
       !IS_BITFIELD (type) &&
       !IS_FLOAT (type) &&
@@ -2051,7 +2076,9 @@ geniCodeDivision (operand * left, operand * right)
   sym_link *ltype = operandType (left);
   sym_link *letype = getSpec (ltype);
 
-  resType = usualBinaryConversions (&left, &right, TRUE, FALSE);
+  resType = usualBinaryConversions (&left, &right,
+              (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE,
+             FALSE);
 
   /* if the right is a literal & power of 2
      and left is unsigned then make it a
@@ -2090,7 +2117,9 @@ geniCodeModulus (operand * left, operand * right)
     return operandFromValue (valMod (left->operand.valOperand,
                                     right->operand.valOperand));
 
-  resType = usualBinaryConversions (&left, &right, TRUE, FALSE);
+  resType = usualBinaryConversions (&left, &right,
+              (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE,
+             FALSE);
 
   /* now they are the same size */
   ic = newiCode ('%', left, right);
@@ -2215,6 +2244,7 @@ geniCodeAdd (operand * left, operand * right, int lvl)
       if (getSize (ltype->next) != 1)
         {
          size  = operandFromLit (getSize (ltype->next));
+         SPEC_USIGN (getSpec (operandType (size))) = 1;
          indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
          right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
          /* Even if right is a 'unsigned char',
@@ -2277,7 +2307,7 @@ aggrToPtr (sym_link * type, bool force)
 /*-----------------------------------------------------------------*/
 /* geniCodeArray2Ptr - array to pointer                            */
 /*-----------------------------------------------------------------*/
-operand *
+static operand *
 geniCodeArray2Ptr (operand * op)
 {
   sym_link *optype = operandType (op);
@@ -2294,10 +2324,11 @@ geniCodeArray2Ptr (operand * op)
 /*-----------------------------------------------------------------*/
 /* geniCodeArray - array access                                    */
 /*-----------------------------------------------------------------*/
-operand *
-geniCodeArray (operand * left, operand * right,int lvl)
+static operand *
+geniCodeArray (operand * left, operand * right, int lvl)
 {
   iCode *ic;
+  operand *size;
   sym_link *ltype = operandType (left);
   bool indexUnsigned;
 
@@ -2310,22 +2341,26 @@ geniCodeArray (operand * left, operand * right,int lvl)
 
       return geniCodeDerefPtr (geniCodeAdd (left, right, lvl), lvl);
     }
+  size = operandFromLit (getSize (ltype->next));
+  SPEC_USIGN (getSpec (operandType (size))) = 1;
   indexUnsigned = IS_UNSIGNED (getSpec (operandType (right)));
-  right = geniCodeMultiply (right,
-                           operandFromLit (getSize (ltype->next)), (getArraySizePtr(left) >= INTSIZE));
+  right = geniCodeMultiply (right, size, (getArraySizePtr(left) >= INTSIZE));
   /* Even if right is a 'unsigned char', the result will be a 'signed int' due to the promotion rules.
      It doesn't make sense when accessing arrays, so let's fix it here: */
   if (indexUnsigned)
     SPEC_USIGN (getSpec (operandType (right))) = 1;
   /* we can check for limits here */
+  /* already done in SDCCast.c
   if (isOperandLiteral (right) &&
       IS_ARRAY (ltype) &&
       DCL_ELEM (ltype) &&
       (operandLitValue (right) / getSize (ltype->next)) >= DCL_ELEM (ltype))
     {
-      werror (E_ARRAY_BOUND);
-      right = operandFromLit (0);
+      werror (W_IDX_OUT_OF_BOUNDS,
+             (int) operandLitValue (right) / getSize (ltype->next),
+             DCL_ELEM (ltype));
     }
+  */
 
   ic = newiCode ('+', left, right);
 
@@ -2730,7 +2765,6 @@ geniCodeLeftShift (operand * left, operand * right)
 {
   iCode *ic;
 
-  left = usualUnaryConversions (left);
   ic = newiCode (LEFT_OP, left, right);
   IC_RESULT (ic) = newiTempOperand (operandType (left), 0);
   ADDTOCHAIN (ic);
@@ -3011,7 +3045,7 @@ geniCodeSEParms (ast * parms,int lvl)
 /*-----------------------------------------------------------------*/
 value *
 geniCodeParms (ast * parms, value *argVals, int *stack, 
-              sym_link * fetype, symbol * func,int lvl)
+              sym_link * ftype, int lvl)
 {
   iCode *ic;
   operand *pval;
@@ -3021,14 +3055,14 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
 
   if (argVals==NULL) {
     // first argument
-    argVals=FUNC_ARGS(func->type);
+    argVals = FUNC_ARGS (ftype);
   }
 
   /* if this is a param node then do the left & right */
   if (parms->type == EX_OP && parms->opval.op == PARAM)
     {
-      argVals=geniCodeParms (parms->left, argVals, stack, fetype, func,lvl);
-      argVals=geniCodeParms (parms->right, argVals, stack, fetype, func,lvl);
+      argVals=geniCodeParms (parms->left, argVals, stack, ftype, lvl);
+      argVals=geniCodeParms (parms->right, argVals, stack, ftype, lvl);
       return argVals;
     }
 
@@ -3052,18 +3086,18 @@ geniCodeParms (ast * parms, value *argVals, int *stack,
     }
 
   /* if register parm then make it a send */
-  if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(func->type)) ||
-      IFFUNC_ISBUILTIN(func->type))
+  if ((IS_REGPARM (parms->etype) && !IFFUNC_HASVARARGS(ftype)) ||
+      IFFUNC_ISBUILTIN(ftype))
     {
       ic = newiCode (SEND, pval, NULL);
       ic->argreg = SPEC_ARGREG(parms->etype);
-      ic->builtinSEND = FUNC_ISBUILTIN(func->type);
+      ic->builtinSEND = FUNC_ISBUILTIN(ftype);
       ADDTOCHAIN (ic);
     }
   else
     {
       /* now decide whether to push or assign */
-      if (!(options.stackAuto || IFFUNC_ISREENT (func->type)))
+      if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
        {
 
          /* assign */
@@ -3097,6 +3131,7 @@ geniCodeCall (operand * left, ast * parms,int lvl)
   iCode *ic;
   operand *result;
   sym_link *type, *etype;
+  sym_link *ftype;
   int stack = 0;
 
   if (!IS_FUNC(OP_SYMBOL(left)->type) && 
@@ -3110,8 +3145,12 @@ geniCodeCall (operand * left, ast * parms,int lvl)
      of overlaying function parameters */
   geniCodeSEParms (parms,lvl);
 
+  ftype = operandType (left);
+  if (IS_CODEPTR (ftype))
+    ftype = ftype->next;
+    
   /* first the parameters */
-  geniCodeParms (parms, NULL, &stack, getSpec (operandType (left)), OP_SYMBOL (left),lvl);
+  geniCodeParms (parms, NULL, &stack, ftype, lvl);
 
   /* now call : if symbol then pcall */
   if (IS_OP_POINTER (left) || IS_ITEMP(left)) {
@@ -3120,7 +3159,7 @@ geniCodeCall (operand * left, ast * parms,int lvl)
     ic = newiCode (CALL, left, NULL);
   }
 
-  type = copyLinkChain (operandType (left)->next);
+  type = copyLinkChain (ftype->next);
   etype = getSpec (type);
   SPEC_EXTR (etype) = 0;
   IC_RESULT (ic) = result = newiTempOperand (type, 1);
@@ -3501,7 +3540,7 @@ geniCodeInline (ast * tree)
 /*-----------------------------------------------------------------*/
 /* geniCodeArrayInit - intermediate code for array initializer     */
 /*-----------------------------------------------------------------*/
-static void 
+static void
 geniCodeArrayInit (ast * tree, operand *array)
 {
   iCode *ic;
@@ -3777,7 +3816,7 @@ ast2iCode (ast * tree,int lvl)
        return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
     case '-':
-      if (right) 
+      if (right)
        return geniCodeSubtract (geniCodeRValue (left, FALSE),
                                 geniCodeRValue (right, FALSE));
       else