upcast parameters to varargs functions to int or generic pointers where appropriate
[fw/sdcc] / src / SDCCast.c
index 847bc6f5bd256ebcb5d4ab822c2bc7aca9dc94ed..c56f9c822ce329295fef979e8b7284a395e9ba4c 100644 (file)
@@ -588,10 +588,50 @@ int processParms (ast *func, value *defParm,
        return 1;
     }
         
+    /* If this is a varagrs function... */ 
+    if (!defParm && actParm && func->hasVargs )
+    {
+        ast *newType = NULL;
+        
+       if (IS_CAST_OP(actParm) 
+        || (IS_AST_LIT_VALUE(actParm) && actParm->values.literalFromCast))
+       {
+          /* Parameter was explicitly typecast; don't touch it. */
+          return 0;
+       }    
+        
+        /* If it's a small integer, upcast to int. */
+       if (IS_INTEGRAL(actParm->ftype)
+         && getSize(actParm->ftype) < INTSIZE)
+        {
+           newType = newAst_LINK(INTTYPE);
+        }
+        
+        if (IS_PTR(actParm->ftype) && !IS_GENPTR(actParm->ftype))
+        {
+            newType = newAst_LINK(copyLinkChain(actParm->ftype));
+            DCL_TYPE(newType->opval.lnk) = GPOINTER;
+        }
+        
+        if (newType)
+        {
+           /* cast required; change this op to a cast. */
+            ast *parmCopy = resolveSymbols(copyAst(actParm));
+           
+           actParm->type = EX_OP;
+           actParm->opval.op = CAST;
+           actParm->left = newType;
+           actParm->right= parmCopy;
+           decorateType(actParm);           
+        }
+        
+        return 0;
+    }        
+        
     /* if defined parameters ended but actual has not & */
-    /* has a variable argument list or statckAuto       */
+    /* stackAuto                                               */
     if (! defParm && actParm && 
-       (func->hasVargs || options.stackAuto || IS_RENT(fetype)))
+       (options.stackAuto || IS_RENT(fetype)))
        return 0;
     
     resolveSymbols(actParm);
@@ -1506,6 +1546,71 @@ ast *reverseLoop (ast *loop, symbol *sym, ast *init, ast *end)
 
 }
 
+#define DEMAND_INTEGER_PROMOTION
+
+#ifdef DEMAND_INTEGER_PROMOTION
+
+/*-----------------------------------------------------------------*/
+/* walk a tree looking for the leaves. Add a typecast to the given */
+/* type to each value leaf node.                                  */
+/*-----------------------------------------------------------------*/
+void pushTypeCastToLeaves(sym_link *type, ast *node, ast **parentPtr)
+{
+    if (!node)
+    {
+        /* WTF? We should never get here. */
+        return;
+    }
+    
+    if (!node->left && !node->right)
+    {
+        /* We're at a leaf; if it's a value, apply the typecast */
+        if (node->type == EX_VALUE && IS_INTEGRAL(TTYPE(node)))
+        {
+            *parentPtr = decorateType(newNode(CAST,
+                                             newAst_LINK(copyLinkChain(type)),
+                                             node));
+       }
+    }
+    else
+    {
+       if (node->left)
+       {
+           pushTypeCastToLeaves(type, node->left, &(node->left));
+       }
+       if (node->right)
+       {
+            pushTypeCastToLeaves(type, node->right, &(node->right));
+       }
+    }
+}
+
+#endif
+
+/*-----------------------------------------------------------------*/
+/* Given an assignment operation in a tree, determine if the LHS   */
+/* (the result) has a different (integer) type than the RHS.      */
+/* If so, walk the RHS and add a typecast to the type of the LHS   */
+/* to all leaf nodes.                                             */
+/*-----------------------------------------------------------------*/
+void propAsgType(ast *tree)
+{
+#ifdef DEMAND_INTEGER_PROMOTION
+    if (!IS_INTEGRAL(LTYPE(tree)) || !IS_INTEGRAL(RTYPE(tree)))
+    {
+       /* Nothing to do here... */
+       return;
+    }
+    
+    if (getSize(LTYPE(tree)) > getSize(RTYPE(tree)))
+    {
+        pushTypeCastToLeaves(LTYPE(tree), tree->right, &(tree->right));
+    }
+#else
+    (void)tree;
+#endif        
+}
+
 /*-----------------------------------------------------------------*/
 /* decorateType - compute type for this tree also does type cheking*/
 /*          this is done bottom up, since type have to flow upwards*/
@@ -2295,6 +2400,7 @@ ast *decorateType (ast *tree)
            tree->left = NULL;
            tree->right = NULL;
            TTYPE(tree) = tree->opval.val->type;            
+           tree->values.literalFromCast = 1;
        }
        else {
            TTYPE(tree) = LTYPE(tree);
@@ -2463,6 +2569,9 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
        LLVAL(tree) = 1;
+       
+       propAsgType(tree);
+       
        return tree ;
 
     case AND_ASSIGN:
@@ -2487,6 +2596,9 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
        LLVAL(tree) = 1;
+       
+       propAsgType(tree);
+       
        return tree ;
        
        /*------------------------------------------------------------------*/
@@ -2518,6 +2630,9 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
        LLVAL(tree) = 1;
+       
+       propAsgType(tree);
+       
        return tree;
        
        /*------------------------------------------------------------------*/
@@ -2556,6 +2671,9 @@ ast *decorateType (ast *tree)
 
        tree->right = decorateType(newNode('+',copyAst(tree->left),tree->right));
        tree->opval.op = '=';       
+       
+       propAsgType(tree);
+       
        return tree;
        
        /*------------------------------------------------------------------*/
@@ -2608,6 +2726,8 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
 
+        propAsgType(tree);
+
        return tree ;
        
        /*------------------------------------------------------------------*/
@@ -2661,11 +2781,21 @@ ast *decorateType (ast *tree)
        }
        
        /* if there is going to be a casing required then add it */
-       if (checkType(currFunc->type->next,RTYPE(tree)) < 0 ) {
-           tree->right = 
+       if (checkType(currFunc->type->next,RTYPE(tree)) < 0 ) 
+       {
+#ifdef DEMAND_INTEGER_PROMOTION        
+           if (IS_INTEGRAL(currFunc->type->next))
+           {
+               pushTypeCastToLeaves(currFunc->type->next, tree->right, &(tree->right));
+           }
+           else
+#endif     
+           {
+               tree->right = 
                decorateType(newNode(CAST,
                                     newAst_LINK(copyLinkChain(currFunc->type->next)),
                                     tree->right));
+           }
        }
        
        RRVAL(tree) = 1;