upcast parameters to varargs functions to int or generic pointers where appropriate
[fw/sdcc] / src / SDCCast.c
index cc5aff3fbf127e41889a16468c7066b5f2f6c6c3..c56f9c822ce329295fef979e8b7284a395e9ba4c 100644 (file)
@@ -49,8 +49,8 @@ char  buffer[1024];
 int noLineno = 0;
 int noAlloc = 0 ;
 symbol *currFunc ;
-ast  *createIval  (ast *, link *, initList *, ast *);
-ast *createIvalCharPtr (ast *, link *, ast *);
+ast  *createIval  (ast *, sym_link *, initList *, ast *);
+ast *createIvalCharPtr (ast *, sym_link *, ast *);
 ast *optimizeRRCRLC ( ast * );
 ast *optimizeGetHbit(ast *);
 ast *backPatchLabels (ast *,symbol *,symbol *);
@@ -89,7 +89,7 @@ ast  *newAst (int  type, void *op )
        ex->opval.op   = (long) op ;
        break ;
     case EX_LINK   :
-       ex->opval.lnk  = (link *) op;
+       ex->opval.lnk  = (sym_link *) op;
        break ;
     case EX_STMNT  :
        ex->opval.stmnt= (unsigned) op;
@@ -129,7 +129,7 @@ ast* newAst_OP(unsigned op)
       return ex;
 }
 
-ast* newAst_LINK(link*val)
+ast* newAst_LINK(sym_link*val)
 {
       ast* ex = newAst_(EX_LINK);
       ex->opval.lnk = val;
@@ -490,7 +490,7 @@ value *resolveFromTable (value *val)
 /*-----------------------------------------------------------------*/
 /* funcOfType :- function of type with name                        */
 /*-----------------------------------------------------------------*/
-symbol *funcOfType (char *name, link *type, link *argType, 
+symbol *funcOfType (char *name, sym_link *type, sym_link *argType, 
                    int nArgs , int rent)
 {
     symbol *sym;    
@@ -559,7 +559,7 @@ int processParms (ast *func, value *defParm,
                  ast *actParm, 
                  int *parmNumber)
 {
-    link *fetype = func->etype;
+    sym_link *fetype = func->etype;
     
     /* if none of them exist */
     if ( !defParm && !actParm)
@@ -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);
@@ -635,7 +675,7 @@ int processParms (ast *func, value *defParm,
 /*-----------------------------------------------------------------*/
 /* createIvalType - generates ival for basic types                 */
 /*-----------------------------------------------------------------*/
-ast *createIvalType ( ast *sym,link  *type, initList *ilist)
+ast *createIvalType ( ast *sym,sym_link  *type, initList *ilist)
 {
     ast *iExpr;
 
@@ -650,7 +690,7 @@ ast *createIvalType ( ast *sym,link  *type, initList *ilist)
 /*-----------------------------------------------------------------*/
 /* createIvalStruct - generates initial value for structures       */
 /*-----------------------------------------------------------------*/
-ast *createIvalStruct (ast *sym,link *type,initList *ilist)
+ast *createIvalStruct (ast *sym,sym_link *type,initList *ilist)
 {
     ast *rast = NULL ;
     symbol   *sflds  ;
@@ -682,7 +722,7 @@ ast *createIvalStruct (ast *sym,link *type,initList *ilist)
 /*-----------------------------------------------------------------*/
 /* createIvalArray - generates code for array initialization       */
 /*-----------------------------------------------------------------*/
-ast *createIvalArray (ast  *sym, link *type, initList *ilist)
+ast *createIvalArray (ast  *sym, sym_link *type, initList *ilist)
 {
     ast *rast = NULL;
     initList *iloop ;
@@ -739,7 +779,7 @@ ast *createIvalArray (ast  *sym, link *type, initList *ilist)
 /*-----------------------------------------------------------------*/
 /* createIvalCharPtr - generates initial values for char pointers  */
 /*-----------------------------------------------------------------*/
-ast *createIvalCharPtr (ast *sym, link *type, ast *iexpr)
+ast *createIvalCharPtr (ast *sym, sym_link *type, ast *iexpr)
 {      
     ast *rast = NULL ;
 
@@ -786,7 +826,7 @@ ast *createIvalCharPtr (ast *sym, link *type, ast *iexpr)
 /*-----------------------------------------------------------------*/
 /* createIvalPtr - generates initial value for pointers            */
 /*-----------------------------------------------------------------*/
-ast *createIvalPtr (ast *sym,link *type,initList *ilist)
+ast *createIvalPtr (ast *sym,sym_link *type,initList *ilist)
 {    
     ast *rast;
     ast *iexpr ;
@@ -808,7 +848,7 @@ ast *createIvalPtr (ast *sym,link *type,initList *ilist)
 /*-----------------------------------------------------------------*/
 /* createIval - generates code for initial value                   */
 /*-----------------------------------------------------------------*/
-ast  *createIval  (ast *sym, link *type, initList *ilist, ast *wid)
+ast  *createIval  (ast *sym, sym_link *type, initList *ilist, ast *wid)
 {
     ast *rast = NULL;  
 
@@ -1475,7 +1515,7 @@ ast *reverseLoop (ast *loop, symbol *sym, ast *init, ast *end)
                forbody
                <sym> -= 1;
                if (sym) goto for_continue ; 
-               <sym> = end - 1; */
+               <sym> = end */
     
     /* put it together piece by piece */
     rloop = newNode (NULLOP,
@@ -1485,8 +1525,7 @@ ast *reverseLoop (ast *loop, symbol *sym, ast *init, ast *end)
                                      NULL),NULL),
                     newNode('=',
                             newAst_VALUE(symbolVal(sym)),
-                            newNode('-', end,
-                                    newAst_VALUE(constVal("1")))));
+                            end));
 
     replLoopSym(loop->left, sym);
 
@@ -1507,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*/
@@ -1515,7 +1619,7 @@ ast *reverseLoop (ast *loop, symbol *sym, ast *init, ast *end)
 ast *decorateType (ast *tree)
 {         
     int parmNumber ;
-    link *p;
+    sym_link *p;
     
     if ( ! tree )
        return tree ;
@@ -1704,7 +1808,7 @@ ast *decorateType (ast *tree)
     case  INC_OP:  /* incerement operator unary so left only */
     case  DEC_OP:
        {
-           link *ltc = (tree->right ? RTYPE(tree) : LTYPE(tree) );
+           sym_link *ltc = (tree->right ? RTYPE(tree) : LTYPE(tree) );
            COPYTYPE(TTYPE(tree),TETYPE(tree),ltc);
            if (!tree->initMode && IS_CONSTANT(TETYPE(tree)))
                werror(E_CODE_WRITE,"++/--");
@@ -2296,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);
@@ -2464,6 +2569,9 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
        LLVAL(tree) = 1;
+       
+       propAsgType(tree);
+       
        return tree ;
 
     case AND_ASSIGN:
@@ -2488,6 +2596,9 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
        LLVAL(tree) = 1;
+       
+       propAsgType(tree);
+       
        return tree ;
        
        /*------------------------------------------------------------------*/
@@ -2519,6 +2630,9 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
        LLVAL(tree) = 1;
+       
+       propAsgType(tree);
+       
        return tree;
        
        /*------------------------------------------------------------------*/
@@ -2557,6 +2671,9 @@ ast *decorateType (ast *tree)
 
        tree->right = decorateType(newNode('+',copyAst(tree->left),tree->right));
        tree->opval.op = '=';       
+       
+       propAsgType(tree);
+       
        return tree;
        
        /*------------------------------------------------------------------*/
@@ -2609,6 +2726,8 @@ ast *decorateType (ast *tree)
            goto errorTreeReturn ;      
        }
 
+        propAsgType(tree);
+
        return tree ;
        
        /*------------------------------------------------------------------*/
@@ -2662,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;
@@ -2753,7 +2882,7 @@ ast *decorateType (ast *tree)
 /*-----------------------------------------------------------------*/
 /* sizeofOp - processes size of operation                          */
 /*-----------------------------------------------------------------*/
-value  *sizeofOp( link  *type)
+value  *sizeofOp( sym_link  *type)
 {
        char buff[10];
 
@@ -3566,7 +3695,7 @@ ast  *createFunction   (symbol  *name,   ast  *body )
     ast  *ex ;
     symbol *csym;
     int stack = 0 ;
-    link *fetype;       
+    sym_link *fetype;       
     iCode *piCode = NULL;
     
     /* if check function return 0 then some problem */