added option parms-in-bank1
[fw/sdcc] / src / SDCCast.c
index 0152f09f1b40eabf5936dd18de2273ad94f26e27..4e92814703d6836911229db21266e698fb73ab4f 100644 (file)
@@ -50,6 +50,7 @@ int noAlloc = 0;
 symbol *currFunc;
 static ast *createIval (ast *, sym_link *, initList *, ast *);
 static ast *createIvalCharPtr (ast *, sym_link *, ast *);
+static ast *optimizeCompare (ast *);
 ast *optimizeRRCRLC (ast *);
 ast *optimizeGetHbit (ast *);
 ast *backPatchLabels (ast *, symbol *, symbol *);
@@ -209,7 +210,7 @@ copyAstValues (ast * dest, ast * src)
 /* copyAst - makes a copy of a given astession                     */
 /*-----------------------------------------------------------------*/
 ast *
-copyAst (ast * src)
+copyAst (ast * src) 
 {
   ast *dest;
 
@@ -255,6 +256,31 @@ exit:
 
 }
 
+/*-----------------------------------------------------------------*/
+/* removeIncDecOps: remove for side effects in *_ASSIGN's          */
+/*                  "*s++ += 3" -> "*s++ = *s++ + 3"               */
+/*-----------------------------------------------------------------*/
+ast *removeIncDecOps (ast * tree) {
+
+  // traverse the tree and remove inc/dec ops
+
+  if (!tree)
+    return NULL;
+
+  if (tree->type == EX_OP && 
+      (tree->opval.op == INC_OP || tree->opval.op == DEC_OP)) {
+    if (tree->left)
+      tree=tree->left;
+    else 
+      tree=tree->right;
+  }
+
+  tree->left=removeIncDecOps(tree->left);
+  tree->right=removeIncDecOps(tree->right);
+ return tree;
+}
+
 /*-----------------------------------------------------------------*/
 /* hasSEFcalls - returns TRUE if tree has a function call          */
 /*-----------------------------------------------------------------*/
@@ -479,7 +505,7 @@ funcOfType (char *name, sym_link * type, sym_link * argType,
   DCL_TYPE (sym->type) = FUNCTION;
   sym->type->next = copyLinkChain (type);
   sym->etype = getSpec (sym->type);
-  FUNC_ISREENT(sym->type) = rent;
+  FUNC_ISREENT(sym->type) = rent ? 1 : 0;
 
   /* if arguments required */
   if (nArgs)
@@ -727,6 +753,7 @@ processParms (ast * func,
   /* make a copy and change the regparm type to the defined parm */
   actParm->etype = getSpec (actParm->ftype = copyLinkChain (actParm->ftype));
   SPEC_REGPARM (actParm->etype) = SPEC_REGPARM (defParm->etype);
+  SPEC_ARGREG  (actParm->etype) = SPEC_ARGREG (defParm->etype);
   (*parmNumber)++;
   return 0;
 }
@@ -924,6 +951,13 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
                               newNode ('[', sym,
                                   newAst_VALUE (valueFromLit ((float) i))),
                               newAst_VALUE (valueFromLit (*s))));
+
+      // now we don't need iexpr's symbol anymore
+      {
+       symbol *sym=AST_SYMBOL(iexpr);
+       memmap *segment=SPEC_OCLS(sym->etype);
+       deleteSetItem(&segment->syms, sym);
+      }
       return decorateType (resolveSymbols (rast));
     }
 
@@ -1146,6 +1180,65 @@ processBlockVars (ast * tree, int *stack, int action)
   return tree;
 }
 
+/*-------------------------------------------------------------*/
+/* constExprTree - returns TRUE if this tree is a constant     */
+/*                 expression                                  */
+/*-------------------------------------------------------------*/
+bool constExprTree (ast *cexpr) {
+
+  if (!cexpr) {
+    return TRUE;
+  }
+
+  cexpr = decorateType (resolveSymbols (cexpr));
+  
+  switch (cexpr->type) 
+    {
+    case EX_VALUE:
+      if (IS_AST_LIT_VALUE(cexpr)) {
+       // this is a literal
+       return TRUE;
+      }
+      if (IS_AST_SYM_VALUE(cexpr) && IS_FUNC(AST_SYMBOL(cexpr)->type)) {
+       // a function's address will never change
+       return TRUE;
+      }
+      if (IS_AST_SYM_VALUE(cexpr) && 
+         IN_CODESPACE(SPEC_OCLS(AST_SYMBOL(cexpr)->etype))) {
+       // a symbol in code space will never change
+       // This is only for the 'char *s="hallo"' case and will have to leave
+       return TRUE;
+      }
+      return FALSE;
+    case EX_LINK:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "unexpected link in expression tree\n");
+      return FALSE;
+    case EX_OP:
+      if (cexpr->opval.op==ARRAYINIT) {
+       // this is a list of literals
+       return TRUE;
+      }
+      if (cexpr->opval.op=='=') {
+       return constExprTree(cexpr->right);
+      }
+      if (cexpr->opval.op==CAST) {
+       // jwk: cast ignored, maybe we should throw a warning here
+       return constExprTree(cexpr->right);
+      }
+      if (cexpr->opval.op=='&') { 
+       return TRUE;
+      }
+      if (cexpr->opval.op==CALL || cexpr->opval.op==PCALL) {
+       return FALSE;
+      }
+      if (constExprTree(cexpr->left) && constExprTree(cexpr->right)) {
+       return TRUE;
+      }
+    }
+  return FALSE;
+}  
+    
 /*-----------------------------------------------------------------*/
 /* constExprValue - returns the value of a constant expression     */
 /*                  or NULL if it is not a constant expression     */
@@ -1176,9 +1269,9 @@ constExprValue (ast * cexpr, int check)
       /* if we are casting a literal value then */
       if (IS_AST_OP (cexpr) &&
          cexpr->opval.op == CAST &&
-         IS_LITERAL (cexpr->left->ftype))
+         IS_LITERAL (cexpr->right->ftype))
        return valCastLiteral (cexpr->ftype,
-                              floatFromVal (cexpr->left->opval.val));
+                              floatFromVal (cexpr->right->opval.val));
 
       if (IS_AST_VALUE (cexpr))
        return cexpr->opval.val;
@@ -1548,9 +1641,16 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       if (astHasVolatile (pbody->left))
        return FALSE;
 
-      if (IS_AST_SYM_VALUE (pbody->left) &&
-         isSymbolEqual (AST_SYMBOL (pbody->left), sym))
-       return FALSE;
+      if (IS_AST_SYM_VALUE (pbody->left)) {
+       // if the loopvar has an assignment
+       if (isSymbolEqual (AST_SYMBOL (pbody->left), sym))
+         return FALSE;
+       // if the loopvar is used in another (maybe conditional) block
+       if (astHasSymbol (pbody->right, sym) &&
+           (pbody->level > body->level)) {
+         return FALSE;
+       }
+      }
 
       if (astHasVolatile (pbody->left))
        return FALSE;
@@ -1584,6 +1684,9 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
       /*       function call        */
 /*----------------------------*/
     case CALL:
+       /* if local & not passed as paramater then ok */
+       if (sym->level && !astHasSymbol(pbody->right,sym)) 
+           return TRUE;
       return FALSE;
 
 /*------------------------------------------------------------------*/
@@ -2883,6 +2986,7 @@ decorateType (ast * tree)
       return tree;
 
 
+#if 0 // assignment operators are converted by the parser
       /*------------------------------------------------------------------*/
       /*----------------------------*/
       /*    assignment operators    */
@@ -3015,6 +3119,7 @@ decorateType (ast * tree)
       tree->opval.op = '=';
 
       return tree;
+#endif
 
       /*------------------------------------------------------------------*/
       /*----------------------------*/
@@ -3032,13 +3137,8 @@ decorateType (ast * tree)
       if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
        {
          werror (E_TYPE_MISMATCH, "assignment", " ");
-         fprintf (stderr, "type --> '");
-         printTypeChain (RTYPE (tree), stderr);
-         fprintf (stderr, "' ");
-         fprintf (stderr, "assigned to type --> '");
-         printTypeChain (LTYPE (tree), stderr);
-         fprintf (stderr, "'\n");
-         goto errorTreeReturn;
+         printFromToType(RTYPE(tree),LTYPE(tree));
+         //goto errorTreeReturn;
        }
 
       /* if the left side of the tree is of type void
@@ -3904,7 +4004,7 @@ tryNext2:
 /*-----------------------------------------------------------------*/
 /* optimizeCompare - otimizes compares for bit variables     */
 /*-----------------------------------------------------------------*/
-ast *
+static ast *
 optimizeCompare (ast * root)
 {
   ast *optExpr = NULL;
@@ -3951,63 +4051,6 @@ optimizeCompare (ast * root)
   vright = (root->right->type == EX_VALUE ?
            root->right->opval.val : NULL);
 
-  //#define EXPERIMENTAL
-#ifdef EXPERIMENTAL
-  /* if left is unsigned and right is literal */
-  if (vleft && vright && 
-      IS_UNSIGNED(vleft->etype) &&
-      IS_LITERAL(vright->etype)) {
-    double dval=floatFromVal(vright);
-    int op=root->opval.op;
-
-    fprintf (stderr,"op: '");
-    switch (op) {
-    case LE_OP: fprintf (stderr, "<= '"); break;
-    case EQ_OP: fprintf (stderr, "== '"); break;
-    case GE_OP: fprintf (stderr, ">= '"); break;
-    default: fprintf (stderr, "%c '", op); break;
-    }
-    fprintf (stderr, "%f\n", dval);
-
-    switch (op)
-      {
-      case EQ_OP:
-      case LE_OP:
-      case '<':
-       if (dval<0 || (op=='<' && dval==0)) {
-         // unsigned is never < 0
-         werror (W_IF_NEVER_TRUE);
-         optExpr = newAst_VALUE (constVal("0"));
-         return decorateType (optExpr);
-       }
-       if (dval==0) {
-         if (op==LE_OP) {
-           // change this into a cheaper EQ_OP
-           fprintf (stderr, "warning *** changed '<=' to '==' because of unsigned\n");
-           root->opval.op=EQ_OP;
-           return root;
-         }
-       }
-       break;
-      case GE_OP:
-      case '>':
-       if (dval>0 || (op==GE_OP && dval==0)) {
-         // unsigned is never < 0
-         werror (W_IF_ALWAYS_TRUE);
-         optExpr = newAst_VALUE (constVal("1"));
-         return decorateType (optExpr);
-       }
-       if (dval==0) {
-         if (op=='>') {
-           // change this into a cheaper reversed EQ_OP
-           fprintf (stderr, "warning *** changed '>' to '!=' because of unsigned\n");
-           root->opval.op=EQ_OP;
-         }
-       }
-      }
-  }
-#endif
-
   /* if left is a BITVAR in BITSPACE */
   /* and right is a LITERAL then opt- */
   /* imize else do nothing       */
@@ -4873,7 +4916,9 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                /*----------------------------*/
        case RETURN:
                fprintf(outfile,"RETURN (%p) type (",tree);
-               printTypeChain(tree->right->ftype,outfile);
+               if (tree->right) {
+                   printTypeChain(tree->right->ftype,outfile);
+               }
                fprintf(outfile,")\n");
                ast_print(tree->right,outfile,indent+2);
                return ;