Slade Rich fixed an optimization bug
[fw/sdcc] / src / SDCCsymt.c
index 35360f205052fbecca4a9b47538cd5220e1a60bc..d3bfee79b661bfee51ab05509da4d5798c60753d 100644 (file)
@@ -973,39 +973,82 @@ addSymChain (symbol * symHead)
 {
   symbol *sym = symHead;
   symbol *csym = NULL;
+  int error = 0;
 
   for (; sym != NULL; sym = sym->next)
     {
       changePointer(sym);
       checkTypeSanity(sym->etype, sym->name);
 
+      if (!sym->level && !(IS_SPEC(sym->etype) && IS_TYPEDEF(sym->etype)))
+        checkDecl (sym, 0);
+      
       /* if already exists in the symbol table then check if
          one of them is an extern definition if yes then
          then check if the type match, if the types match then
          delete the current entry and add the new entry      */
       if ((csym = findSymWithLevel (SymbolTab, sym)) &&
          csym->level == sym->level) {
-       
-       /* one definition extern ? */
-       if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype)) {
-         /* do types match ? */
-         if (compareType (csym->type, sym->type) != 1) {
-           /* no then error */
-           werror (E_EXTERN_MISMATCH, csym->name);
-           continue;
+
+       /* If the previous definition was for an array with incomplete */
+       /* type, and the new definition has completed the type, update */
+       /* the original type to match */
+       if (IS_DECL(csym->type) && DCL_TYPE(csym->type)==ARRAY
+           && IS_DECL(sym->type) && DCL_TYPE(sym->type)==ARRAY)
+         {
+           if (!DCL_ELEM(csym->type) && DCL_ELEM(sym->type))
+             DCL_ELEM(csym->type) = DCL_ELEM(sym->type);
          }
-       } else {
-         /* not extern */
-         if (compareType (csym->type, sym->type) != 1) {
-           werror (E_DUPLICATE, sym->name);
-           continue;
+
+       #if 0
+       /* If only one of the definitions used the "at" keyword, copy */
+       /* the address to the other. */
+       if (IS_SPEC(csym->etype) && SPEC_ABSA(csym->etype)
+           && IS_SPEC(sym->etype) && !SPEC_ABSA(sym->etype))
+         {
+           SPEC_ABSA (sym->etype) = 1;
+           SPEC_ADDR (sym->etype) = SPEC_ADDR (csym->etype);
+         }
+       if (IS_SPEC(csym->etype) && !SPEC_ABSA(csym->etype)
+           && IS_SPEC(sym->etype) && SPEC_ABSA(sym->etype))
+         {
+           SPEC_ABSA (csym->etype) = 1;
+           SPEC_ADDR (csym->etype) = SPEC_ADDR (sym->etype);
          }
+       #endif
+  
+        error = 0;        
+        if (csym->ival && sym->ival)
+          error = 1;
+       if (compareTypeExact (csym->type, sym->type, sym->level) != 1)
+          error = 1;
+        
+        if (error) {
+          /* one definition extern ? */
+         if (IS_EXTERN (csym->etype) || IS_EXTERN (sym->etype))
+           werror (E_EXTERN_MISMATCH, sym->name);
+          else
+           werror (E_DUPLICATE, sym->name);
+         fprintf (stderr, "from type '");
+         printTypeChain (csym->type, stderr);
+         if (IS_SPEC (csym->etype) && SPEC_ABSA (csym->etype))
+           fprintf(stderr, " at 0x%x", SPEC_ADDR (csym->etype));
+         fprintf (stderr, "'\nto type '");
+         printTypeChain (sym->type, stderr);
+         if (IS_SPEC (sym->etype) && SPEC_ABSA (sym->etype))
+           fprintf(stderr, " at 0x%x", SPEC_ADDR (sym->etype));
+         fprintf (stderr, "'\n");
+         continue;
        }
+
+       if (csym->ival && !sym->ival)
+         sym->ival = csym->ival;
+
        /* delete current entry */
        deleteSym (SymbolTab, csym, csym->name);
        deleteFromSeg(csym);
       }
-
+      
       /* add new entry */
       addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
     }
@@ -1295,7 +1338,7 @@ checkSClass (symbol * sym, int isProto)
       }
     }
   }
-  
+
   /* automatic symbols cannot be given   */
   /* an absolute address ignore it      */
   if (sym->level &&
@@ -1470,7 +1513,7 @@ cleanUpLevel (bucket ** table, int level)
 /* computeType - computes the resultant type from two types         */
 /*------------------------------------------------------------------*/
 sym_link *
-computeType (sym_link * type1, sym_link * type2)
+computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
 {
   sym_link *rType;
   sym_link *reType;
@@ -1503,14 +1546,25 @@ computeType (sym_link * type1, sym_link * type2)
     rType = copyLinkChain (type2);
 
   reType = getSpec (rType);
-#if 0
-  if (SPEC_NOUN (reType) == V_CHAR)
+
+  /* avoid conflicting types */
+  reType->select.s._signed = 0;
+
+  if (IS_CHAR (reType) && promoteCharToInt)
     SPEC_NOUN (reType) = V_INT;
-#endif
 
-  /* if either of them unsigned but not val then make this unsigned */
-  if ((SPEC_USIGN (etype1) || SPEC_USIGN (etype2)) &&
-      !IS_FLOAT (reType))
+  if (   (   (   SPEC_USIGN (etype1)
+              /* if this operand is promoted to a larger
+                type don't check it's signedness */
+             && (getSize (etype1) >= getSize (reType))
+             /* We store signed literals in the range 0...255 as
+                'unsigned char'. If there was no promotion to 'signed int'
+                they must not force an unsigned operation: */
+             && !(IS_CHAR (etype1) && IS_LITERAL (etype1)))
+         || (   SPEC_USIGN (etype2)
+             && (getSize (etype2) >= getSize (reType))
+             && !(IS_CHAR (etype2) && IS_LITERAL (etype2))))
+      && !IS_FLOAT (reType))
     SPEC_USIGN (reType) = 1;
   else
     SPEC_USIGN (reType) = 0;
@@ -1619,6 +1673,185 @@ compareType (sym_link * dest, sym_link * src)
   return 1;
 }
 
+/*--------------------------------------------------------------------*/
+/* compareTypeExact - will do type check return 1 if match exactly    */
+/*--------------------------------------------------------------------*/
+int
+compareTypeExact (sym_link * dest, sym_link * src, int level)
+{
+  STORAGE_CLASS srcScls, destScls;
+  
+  if (!dest && !src)
+    return 1;
+
+  if (dest && !src)
+    return 0;
+
+  if (src && !dest)
+    return 0;
+
+  /* if dest is a declarator then */
+  if (IS_DECL (dest))
+    {
+      if (IS_DECL (src))
+       {
+         if (DCL_TYPE (src) == DCL_TYPE (dest)) {
+           if ((DCL_TYPE (src) == ARRAY) && (DCL_ELEM (src) != DCL_ELEM (dest)))
+             return 0;
+           if (DCL_PTR_CONST (src) != DCL_PTR_CONST (dest))
+             return 0;
+           if (DCL_PTR_VOLATILE (src) != DCL_PTR_VOLATILE (dest))
+             return 0;
+           if (IS_FUNC(src))
+              {
+               value *exargs, *acargs, *checkValue;
+
+                /* verify function return type */
+               if (!compareTypeExact (dest->next, src->next, -1))
+                 return 0;
+               if (FUNC_ISISR (dest) != FUNC_ISISR (src))
+                 return 0;
+               if (FUNC_REGBANK (dest) != FUNC_REGBANK (src))
+                 return 0;
+               if (IFFUNC_ISNAKED (dest) != IFFUNC_ISNAKED (src))
+                 return 0;
+               #if 0
+                if (IFFUNC_ISREENT (dest) != IFFUNC_ISREENT (src) && argCnt>1)
+                 return 0;
+                #endif
+
+               /* compare expected args with actual args */
+               exargs = FUNC_ARGS(dest);
+               acargs = FUNC_ARGS(src);
+
+               /* for all the expected args do */
+               for (; exargs && acargs; exargs = exargs->next, acargs = acargs->next)
+                 {
+                   //checkTypeSanity(acargs->etype, acargs->name);
+
+                   if (IS_AGGREGATE (acargs->type))
+                     {
+                       checkValue = copyValue (acargs);
+                       aggregateToPointer (checkValue);
+                     }
+                   else
+                     checkValue = acargs;
+
+                    #if 0
+                   if (!compareTypeExact (exargs->type, checkValue->type, -1))
+                      return 0;
+                    #endif
+                 }
+
+                 /* if one them ended we have a problem */
+                 if ((exargs && !acargs && !IS_VOID (exargs->type)) ||
+                     (!exargs && acargs && !IS_VOID (acargs->type)))
+                   return 0;                  
+                  return 1;
+              }
+           return compareTypeExact (dest->next, src->next, level);
+         }
+          return 0;
+       }
+      return 0;
+    }
+
+  /* if one is a specifier and the other is not */
+  if ((IS_SPEC (src) && !IS_SPEC (dest)) ||
+      (IS_SPEC (dest) && !IS_SPEC (src)))
+    return 0;
+
+  /* if one of them is a void then ok */
+  if (SPEC_NOUN (dest) != SPEC_NOUN (src))
+    return 0;
+
+  /* if they are both bitfields then if the lengths
+     and starts don't match */
+  if (IS_BITFIELD (dest) && IS_BITFIELD (src) &&
+      (SPEC_BLEN (dest) != SPEC_BLEN (src) ||
+       SPEC_BSTR (dest) != SPEC_BSTR (src)))
+    return 0;
+
+  if (IS_INTEGRAL (dest))
+    {
+      /* signedness must match */
+      if (SPEC_USIGN (dest) != SPEC_USIGN (src))
+       return 0;
+      /* size must match */
+      if (SPEC_LONG (dest) != SPEC_LONG (src))
+       return 0;
+      if (SPEC_SHORT (dest) != SPEC_SHORT (src))
+       return 0;
+    }
+  
+  if (IS_STRUCT (dest))
+    {
+      if (SPEC_STRUCT (dest) != SPEC_STRUCT (src))
+       return 0;
+    }
+
+  if (SPEC_CONST (dest) != SPEC_CONST (src))
+    return 0;
+  if (SPEC_VOLATILE (dest) != SPEC_VOLATILE (src))
+    return 0;
+  if (SPEC_STAT (dest) != SPEC_STAT (src))
+    return 0;
+  if (SPEC_ABSA (dest) != SPEC_ABSA (src))
+    return 0;
+  if (SPEC_ABSA (dest) && SPEC_ADDR (dest) != SPEC_ADDR (src))
+    return 0;
+      
+  destScls = SPEC_SCLS (dest);
+  srcScls = SPEC_SCLS (src);
+  
+  /* Compensate for const to const code change in checkSClass() */
+  if (!level & port->mem.code_ro && SPEC_CONST (dest))
+    {
+      if (srcScls == S_CODE && destScls == S_FIXED)
+       destScls = S_CODE;
+      if (destScls == S_CODE && srcScls == S_FIXED)
+       srcScls = S_CODE;
+    }
+
+  /* compensate for allocGlobal() */  
+  if ((srcScls == S_FIXED || srcScls == S_AUTO)
+      && port->mem.default_globl_map == xdata
+      && !level)
+    srcScls = S_XDATA;
+  
+  if (level>0 && !SPEC_STAT (dest))
+    {
+      /* Compensate for hack-o-matic in checkSClass() */
+      if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type)))
+       {
+         if (destScls == S_FIXED)
+           destScls = (options.useXstack ? S_XSTACK : S_STACK);
+         if (srcScls == S_FIXED)
+           srcScls = (options.useXstack ? S_XSTACK : S_STACK);
+       }
+      else if (TARGET_IS_DS390 || TARGET_IS_DS400 || options.useXstack)
+       {
+         if (destScls == S_FIXED)
+           destScls = S_XDATA;
+         if (srcScls == S_FIXED)
+           srcScls = S_XDATA;
+       }
+    }
+
+  if (srcScls != destScls)
+    {
+      #if 0
+      printf ("level = %d\n", level);
+      printf ("SPEC_SCLS (src) = %d, SPEC_SCLS (dest) = %d\n",
+               SPEC_SCLS (src), SPEC_SCLS (dest));
+      printf ("srcScls = %d, destScls = %d\n",srcScls, destScls);
+      #endif
+      return 0;
+    }
+  
+  return 1;
+}
+
 /*------------------------------------------------------------------*/
 /* inCalleeSaveList - return 1 if found in callee save list          */
 /*------------------------------------------------------------------*/
@@ -1717,6 +1950,12 @@ checkFunction (symbol * sym, symbol *csym)
     fprintf (stderr, "checkFunction: %s ", sym->name);
   }
 
+  if (!IS_DECL(sym->type) || DCL_TYPE(sym->type)!=FUNCTION)
+    {
+      werror(E_SYNTAX_ERROR, sym->name);
+      return 0;
+    }
+    
   /* make sure the type is complete and sane */
   checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
 
@@ -1995,10 +2234,13 @@ processFuncArgs (symbol * func)
          val->sym->etype = getSpec (val->sym->type);
          val->sym->_isparm = 1;
          strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname));
+         #if 0
+         /* ?? static functions shouldn't imply static parameters - EEP */
          if (IS_SPEC(func->etype)) {
            SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
              SPEC_STAT (func->etype);
          }
+         #endif
          addSymChain (val->sym);
 
        }
@@ -2010,10 +2252,14 @@ processFuncArgs (symbol * func)
          val->sym->_isparm = 1;
          SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
            (options.model != MODEL_SMALL ? xdata : data);
+         
+         #if 0
+         /* ?? static functions shouldn't imply static parameters - EEP */
          if (IS_SPEC(func->etype)) {
            SPEC_STAT (val->etype) = SPEC_STAT (val->sym->etype) =
              SPEC_STAT (func->etype);
          }
+         #endif
        }
       if (!isinSet(operKeyReset, val->sym)) {
        addSet (&operKeyReset, val->sym);
@@ -2400,8 +2646,8 @@ printTypeChainRaw (sym_link * start, FILE * of)
 /*-----------------------------------------------------------------*/
 /* powof2 - returns power of two for the number if number is pow 2 */
 /*-----------------------------------------------------------------*/
-int 
-powof2 (unsigned long num)
+int
+powof2 (TYPE_UDWORD num)
 {
   int nshifts = 0;
   int n1s = 0;
@@ -2444,7 +2690,7 @@ sym_link *floatType;
 static char *
 _mangleFunctionName(char *in)
 {
-  if (port->getMangledFunctionName) 
+  if (port->getMangledFunctionName)
     {
       return port->getMangledFunctionName(in);
     }
@@ -2768,3 +3014,63 @@ sym_link *validateLink(sym_link  *l,
     exit(-1);
     return l; // never reached, makes compiler happy.
 }
+
+/*--------------------------------------------------------------------*/
+/* newEnumType - create an integer type compatible with enumerations  */
+/*--------------------------------------------------------------------*/
+sym_link *
+newEnumType (symbol *enumlist)
+{
+  int min, max, v;
+  symbol *sym;
+  sym_link *type;
+
+  if (!enumlist)
+    {
+      type = newLink (SPECIFIER);
+      SPEC_NOUN (type) = V_INT;
+      return type;
+    }
+      
+  /* Determine the range of the enumerated values */
+  sym = enumlist;
+  min = max = (int) floatFromVal (valFromType (sym->type));
+  for (sym = sym->next; sym; sym = sym->next)
+    {
+      v = (int) floatFromVal (valFromType (sym->type));
+      if (v<min)
+        min = v;
+      if (v>max)
+        max = v;
+    }
+
+  /* Determine the smallest integer type that is compatible with this range */
+  type = newLink (SPECIFIER);
+  if (min>=0 && max<=255)
+    {
+      SPEC_NOUN (type) = V_CHAR;
+      SPEC_USIGN (type) = 1;
+    }
+  else if (min>=-128 && max<=127)
+    {
+      SPEC_NOUN (type) = V_CHAR;
+    }
+  else if (min>=0 && max<=65535)
+    {
+      SPEC_NOUN (type) = V_INT;
+      SPEC_USIGN (type) = 1;
+    }
+  else if (min>=-32768 && max<=32767)
+    {
+      SPEC_NOUN (type) = V_INT;
+    }
+  else
+    {
+      SPEC_NOUN (type) = V_INT;
+      SPEC_LONG (type) = 1;
+      if (min>=0)
+        SPEC_USIGN (type) = 1;
+    }
+  
+  return type;    
+}