#include <at89x2051.h> replaced by #include <8051.h>
[fw/sdcc] / src / SDCCsymt.c
index 0f532e0fefc6c78bd2edef1fb7b5d29a2bbc80c9..bf7a5809103e09b0d31a8218d12a69830267e5aa 100644 (file)
 #include "common.h"
 #include "newalloc.h"
 
+/* noun strings */
+char *nounName(sym_link *sl) {
+  switch (SPEC_NOUN(sl)) 
+    {
+    case V_INT: {
+      if (SPEC_LONG(sl)) return "long";
+      if (SPEC_SHORT(sl)) return "short";
+      return "int";
+    }
+    case V_FLOAT: return "float";
+    case V_CHAR: return "char";
+    case V_VOID: return "void";
+    case V_STRUCT: return "struct";
+    case V_LABEL: return "label";
+    case V_BIT: return "bit";
+    case V_SBIT: return "sbit";
+    case V_DOUBLE: return "double";
+    }
+  return "unknown";
+};
+
 bucket *SymbolTab[256];                /* the symbol    table  */
 bucket *StructTab[256];                /* the structure table  */
 bucket *TypedefTab[256];       /* the typedef   table  */
@@ -82,6 +103,15 @@ addSym (bucket ** stab,
   int i;                       /* index into the hash Table */
   bucket *bp;                  /* temp bucket    *         */
 
+  if (getenv("DEBUG_SANITY")) {
+    fprintf (stderr, "addSym: %s ", sname);
+  }
+  /* Make sure sym is a symbol and not a structdef */
+  if (1 || StructTab!=stab) {
+    /* make sure the type is complete and sane */
+    checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
+  }
+
   /* the symbols are always added at the head of the list  */
   i = hashKey (sname);
   /* get a free entry */
@@ -424,24 +454,125 @@ addDecl (symbol * sym, int type, sym_link * p)
   return;
 }
 
+/*------------------------------------------------------------------
+  checkTypeSanity: prevent the user from doing e.g.:
+  unsigned float uf;
+  ------------------------------------------------------------------*/
+void checkTypeSanity(sym_link *etype, char *name) {
+  char *noun;
+
+  if (!etype) {
+    if (getenv("DEBUG_SANITY")) {
+      fprintf (stderr, "sanity check skipped for %s (etype==0)\n", name);
+    }
+    return;
+  }
+
+  if (!IS_SPEC(etype)) {
+    if (getenv("DEBUG_SANITY")) {
+      fprintf (stderr, "sanity check skipped for %s (!IS_SPEC)\n", name);
+    }
+    return;
+  }
+
+  noun=nounName(etype);
+
+  if (getenv("DEBUG_SANITY")) {
+    fprintf (stderr, "checking sanity for %s\n", name);
+  }
+
+  if ((SPEC_NOUN(etype)==V_CHAR || 
+       SPEC_NOUN(etype)==V_FLOAT || 
+       SPEC_NOUN(etype)==V_DOUBLE || 
+       SPEC_NOUN(etype)==V_VOID) &&
+      (SPEC_SHORT(etype) || SPEC_LONG(etype))) {
+    // long or short for char float double or void
+    werror (E_LONG_OR_SHORT_INVALID, noun, name);
+  }
+  if ((SPEC_NOUN(etype)==V_FLOAT || 
+       SPEC_NOUN(etype)==V_DOUBLE || 
+       SPEC_NOUN(etype)==V_VOID) && 
+      (SPEC_SIGNED(etype) || SPEC_USIGN(etype))) {
+    // signed or unsigned for float double or void
+    werror (E_SIGNED_OR_UNSIGNED_INVALID, noun, name);
+  }
+
+  if (!SPEC_NOUN(etype)) {
+    // special case for just "signed" or "unsigned" or "long"
+    if (SPEC_SIGNED(etype) || SPEC_USIGN(etype) || SPEC_LONG(etype)) {
+      SPEC_NOUN(etype)=V_INT;
+    }
+    // special case for just "short"
+    if (SPEC_SHORT(etype)) {
+      SPEC_NOUN(etype)=V_CHAR; // or maybe V_INT
+      SPEC_SHORT(etype)=0;
+    }
+  }
+
+  // if still no noun (e.g. "const a;" or "data b;") assume an int
+  if (!SPEC_NOUN(etype)) {
+    SPEC_NOUN(etype)=V_INT;
+  }
+
+  if (SPEC_SIGNED(etype) && SPEC_USIGN(etype)) {
+    // signed AND unsigned 
+    werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name);
+  }
+  if (SPEC_SHORT(etype) && SPEC_LONG(etype)) {
+    // short AND long
+    werror (E_LONG_AND_SHORT_INVALID, noun, name);
+  }
+
+}
+
 /*------------------------------------------------------------------*/
-/* mergeSpec - merges two specifiers and returns the new one       */
+/* mergeSpec - merges two specifiers and returns the new one        */
 /*------------------------------------------------------------------*/
 sym_link *
 mergeSpec (sym_link * dest, sym_link * src)
 {
-  /* if noun different then src overrides */
-  if (SPEC_NOUN (dest) != SPEC_NOUN (src) && !SPEC_NOUN (dest))
-    SPEC_NOUN (dest) = SPEC_NOUN (src);
-
-  /* if destination has no storage class */
-  if (!SPEC_SCLS (dest) || (SPEC_SCLS(dest) == S_CONSTANT && SPEC_SCLS (src)))
-    SPEC_SCLS (dest) = SPEC_SCLS (src);
-  /* special case for const */
+
+  if (SPEC_NOUN(src)) {
+    if (!SPEC_NOUN(dest)) {
+      SPEC_NOUN(dest)=SPEC_NOUN(src);
+    } else {
+      /* we shouldn't redeclare the type */
+      if (getenv("DEBUG_SANITY")) {
+       fprintf (stderr, "mergeSpec: ");
+       werror(E_TWO_OR_MORE_DATA_TYPES, yylval.yychar);
+      }
+    }
+  }
+  
+  if (SPEC_SCLS(src)) {
+    /* if destination has no storage class */
+    if (!SPEC_SCLS (dest) || SPEC_SCLS(dest)==S_REGISTER) {
+      SPEC_SCLS (dest) = SPEC_SCLS (src);
+    } else {
+      if (getenv("DEBUG_SANITY")) {
+       fprintf (stderr, "mergeSpec: ");
+      }
+      werror(E_TWO_OR_MORE_STORAGE_CLASSES, yylval.yychar);
+    }
+  }
+
   /* copy all the specifications  */
+
+  // we really should do: 
+#if 0
+  if (SPEC_what(src)) {
+    if (SPEC_what(dest)) {
+      werror(W_DUPLICATE_SPEC, "what");
+    }
+    SPEC_what(dst)=SPEC_what(src);
+  }
+#endif
+  // but there are more important thing right now
+  
   SPEC_LONG (dest) |= SPEC_LONG (src);
   SPEC_SHORT (dest) |= SPEC_SHORT (src);
   SPEC_USIGN (dest) |= SPEC_USIGN (src);
+  SPEC_SIGNED (dest) |= SPEC_SIGNED (src);
   SPEC_STAT (dest) |= SPEC_STAT (src);
   SPEC_EXTR (dest) |= SPEC_EXTR (src);
   SPEC_ABSA (dest) |= SPEC_ABSA (src);
@@ -456,6 +587,7 @@ mergeSpec (sym_link * dest, sym_link * src)
   SPEC_BSTR (dest) |= SPEC_BSTR (src);
   SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
   SPEC_NONBANKED (dest) |= SPEC_NONBANKED (src);
+  SPEC_NAKED (dest) |= SPEC_NAKED (src);
 
   if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
     SPEC_STRUCT (dest) = SPEC_STRUCT (src);
@@ -509,7 +641,7 @@ getSpec (sym_link * p)
 }
 
 /*------------------------------------------------------------------*/
-/* newCharLink() - creates an int type                              */
+/* newCharLink() - creates an char type                             */
 /*------------------------------------------------------------------*/
 sym_link *
 newCharLink ()
@@ -786,8 +918,10 @@ addSymChain (symbol * symHead)
   symbol *sym = symHead;
   symbol *csym = NULL;
 
+
   for (; sym != NULL; sym = sym->next)
     {
+      changePointer(sym);
 
       /* if already exists in the symbol table then check if
          the previous was an extern definition if yes then
@@ -826,7 +960,6 @@ addSymChain (symbol * symHead)
                werror (W_EXTERN_MISMATCH, csym->name);
            }
        }
-
       addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
     }
 }
@@ -1053,7 +1186,6 @@ checkSClass (symbol * sym)
        SPEC_SCLS (sym->etype) != S_XSTACK &&
        SPEC_SCLS (sym->etype) != S_CONSTANT))
     {
-
       werror (E_AUTO_ASSUMED, sym->name);
       SPEC_SCLS (sym->etype) = S_AUTO;
     }
@@ -1096,7 +1228,8 @@ checkSClass (symbol * sym)
 
   /* if parameter or local variable then change */
   /* the storage class to reflect where the var will go */
-  if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED)
+  if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED &&
+      !IS_STATIC(sym->etype))
     {
       if (options.stackAuto || (currFunc && IS_RENT (currFunc->etype)))
        {
@@ -1109,7 +1242,7 @@ checkSClass (symbol * sym)
           * control this allcoation, but the code was originally that way, and
           * changing it for non-390 ports breaks the compiler badly.
           */
-         bool useXdata = IS_DS390_PORT ? options.model : options.useXstack;
+         bool useXdata = TARGET_IS_DS390 ? 1 : options.useXstack;
          SPEC_SCLS (sym->etype) = (useXdata ?
                                    S_XDATA : S_FIXED);
        }
@@ -1419,7 +1552,7 @@ aggregateArgToPointer (value * val)
          DCL_TYPE (val->type) = PPOINTER;
          break;
        case S_FIXED:
-         if (IS_DS390_PORT)
+         if (TARGET_IS_DS390)
            {
              /* The AUTO and REGISTER classes should probably
               * also become generic pointers, but I haven't yet
@@ -1466,6 +1599,13 @@ checkFunction (symbol * sym)
   value *exargs, *acargs;
   int argCnt = 0;
 
+  if (getenv("DEBUG_SANITY")) {
+    fprintf (stderr, "checkFunction: %s ", sym->name);
+  }
+
+  /* make sure the type is complete and sane */
+  checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
+
   /* if not type then some kind of error */
   if (!sym->type)
     return 0;
@@ -1514,7 +1654,7 @@ checkFunction (symbol * sym)
   if (checkType (csym->type, sym->type) <= 0)
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "type");
-      werror (E_CONTINUE, "previous defintion type ");
+      werror (E_CONTINUE, "previous definition type ");
       printTypeChain (csym->type, stderr);
       fprintf (stderr, "\n");
       werror (E_CONTINUE, "current definition type ");
@@ -1592,7 +1732,6 @@ processFuncArgs (symbol * func, int ignoreName)
   value *val;
   int pNum = 1;
 
-
   /* if this function has variable argument list */
   /* then make the function a reentrant one    */
   if (func->hasVargs)
@@ -1619,11 +1758,8 @@ processFuncArgs (symbol * func, int ignoreName)
     {
       /* mark it as a register parameter if
          the function does not have VA_ARG
-         and as port dictates
-         not inhibited by command line option or #pragma */
+         and as port dictates */
       if (!func->hasVargs &&
-         !options.noregparms &&
-         !IS_RENT (func->etype) &&
          (*port->reg_parm) (val->type))
        {
          SPEC_REGPARM (val->etype) = 1;
@@ -1637,10 +1773,19 @@ processFuncArgs (symbol * func, int ignoreName)
       pNum++;
     }
 
-  /* if this function is reentrant or */
-  /* automatics r 2b stacked then nothing */
-  if (IS_RENT (func->etype) || options.stackAuto)
-    return;
+  /* if this is an internal generated function call */
+  if (func->cdef) {
+    /* ignore --stack-auto for this one, we don't know how it is compiled */
+    /* simply trust on --int-long-reent or --float-reent */
+    if (IS_RENT(func->etype)) {
+      return;
+    }
+  } else {
+    /* if this function is reentrant or */
+    /* automatics r 2b stacked then nothing */
+    if (IS_RENT (func->etype) || options.stackAuto)
+      return;
+  }
 
   val = func->args;
   pNum = 1;
@@ -1723,6 +1868,9 @@ printTypeChain (sym_link * type, FILE * of)
     {
       if (IS_DECL (type))
        {
+         if (DCL_PTR_VOLATILE(type)) {
+           fprintf (of, "volatile ");
+         }
          switch (DCL_TYPE (type))
            {
            case FUNCTION:
@@ -1769,7 +1917,6 @@ printTypeChain (sym_link * type, FILE * of)
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
              break;
-
            case ARRAY:
              fprintf (of, "array of ");
              break;
@@ -1789,10 +1936,9 @@ printTypeChain (sym_link * type, FILE * of)
            case V_INT:
              if (IS_LONG (type))
                fprintf (of, "long ");
-             else if (IS_SHORT (type))
+             if (IS_SHORT (type))
                fprintf (of, "short ");
-             else
-               fprintf (of, "int ");
+             fprintf (of, "int ");
              break;
 
            case V_CHAR:
@@ -1819,7 +1965,12 @@ printTypeChain (sym_link * type, FILE * of)
              fprintf (of, "bit {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
              break;
 
+           case V_DOUBLE:
+             fprintf (of, "double ");
+             break;
+
            default:
+             fprintf (of, "unknown type ");
              break;
            }
        }
@@ -2176,7 +2327,7 @@ initCSupport ()
                       smuldivmod[muldivmod],
                       ssu[su],
                       sbwd[bwd]);
-             __muldiv[muldivmod][bwd][su] = funcOfType (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
+              __muldiv[muldivmod][bwd][su] = funcOfType (buffer, __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
              SPEC_NONBANKED (__muldiv[muldivmod][bwd][su]->etype) = 1;
              if (bwd < port->muldiv.force_reg_param_below)
                _makeRegParam (__muldiv[muldivmod][bwd][su]);