* as/mcs51/lkarea.c (lnkarea, lnkarea2): improved BSEG size calculation,
[fw/sdcc] / src / SDCCsymt.c
index b621774b9c7476cef7823c6c55b945b0ad655d8c..91eb064fcfb71ccf79696f64a941cdfd8d4b68b2 100644 (file)
@@ -818,7 +818,7 @@ getSize (sym_link * p)
     case FPOINTER:
     case CPOINTER:
     case FUNCTION:
-      return (FPTRSIZE);
+      return (IFFUNC_BANKED (p) ? GPTRSIZE : FPTRSIZE);
     case GPOINTER:
       return (GPTRSIZE);
 
@@ -1005,15 +1005,16 @@ reverseLink (sym_link * type)
 /* addSymChain - adds a symbol chain to the symboltable             */
 /*------------------------------------------------------------------*/
 void 
-addSymChain (symbol * symHead)
+addSymChain (symbol ** symHead)
 {
-  symbol *sym = symHead;
+  symbol *sym = *symHead;
   symbol *csym = NULL;
+  symbol **symPtrPtr;
   int error = 0;
 
   for (; sym != NULL; sym = sym->next)
     {
-      changePointer(sym);
+      changePointer(sym->type);
       checkTypeSanity(sym->etype, sym->name);
 
       if (!sym->level && !(IS_SPEC(sym->etype) && IS_TYPEDEF(sym->etype)))
@@ -1086,6 +1087,13 @@ addSymChain (symbol * symHead)
         /* delete current entry */
         deleteSym (SymbolTab, csym, csym->name);
         deleteFromSeg(csym);
+        
+        symPtrPtr = symHead;
+        while (*symPtrPtr && *symPtrPtr != csym)
+          symPtrPtr = &(*symPtrPtr)->next;
+        if (*symPtrPtr == csym)
+          *symPtrPtr = csym->next;
+          
       }
       
       /* add new entry */
@@ -1249,7 +1257,7 @@ compStructSize (int su, structdef * sdef)
 
         loop = loop->next;
 
-        /* if union then size = sizeof larget field */
+        /* if union then size = sizeof largest field */
         if (su == UNION) {
             /* For UNION, round up after each field */
             sum += ((bitOffset+7)/8);
@@ -1365,6 +1373,26 @@ checkSClass (symbol * sym, int isProto)
     if (IS_ABSOLUTE (sym->etype))
       SPEC_VOLATILE (sym->etype) = 1;
   
+  if (TARGET_IS_MCS51 &&
+      IS_ABSOLUTE (sym->etype) &&
+      SPEC_SCLS (sym->etype) == S_SFR)
+    {
+      int n, size;
+      unsigned addr;
+
+      if (SPEC_NOUN (sym->etype) == V_CHAR)
+        size = 8;
+      else if (SPEC_LONG (sym->etype) == 0)
+        size = 16;
+      else
+        size = 32;
+
+      addr = SPEC_ADDR (sym->etype);
+      for (n=0; n<size; n+=8)
+        if (((addr >> n) & 0xFF) < 0x80)
+          werror (W_SFR_ABSRANGE, sym->name);
+    }
+
   /* If code memory is read only, then pointers to code memory */
   /* implicitly point to constants -- make this explicit       */
   t = sym->type;
@@ -1485,8 +1513,9 @@ checkSClass (symbol * sym, int isProto)
 
   /* 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 &&
-      !IS_STATIC(sym->etype))
+  if (sym->level && SPEC_SCLS (sym->etype) == S_FIXED
+   && !IS_STATIC(sym->etype)
+      )
     {
       if (options.stackAuto || (currFunc && IFFUNC_ISREENT (currFunc->type)))
         {
@@ -1496,7 +1525,7 @@ checkSClass (symbol * sym, int isProto)
       else
         {
           /* hack-o-matic! I see no reason why the useXstack option should ever
-           * control this allcoation, but the code was originally that way, and
+           * control this allocation, but the code was originally that way, and
            * changing it for non-390 ports breaks the compiler badly.
            */
           bool useXdata = (TARGET_IS_DS390 || TARGET_IS_DS400) ? 
@@ -1511,19 +1540,19 @@ checkSClass (symbol * sym, int isProto)
 /* changePointer - change pointer to functions                      */
 /*------------------------------------------------------------------*/
 void 
-changePointer (symbol * sym)
+changePointer (sym_link * p)
 {
-  sym_link *p;
 
   /* go thru the chain of declarations   */
   /* if we find a pointer to a function  */
-  /* unconditionally change it to a ptr  */
-  /* to code area                        */
-  for (p = sym->type; p; p = p->next)
+  /* change it to a ptr to code area     */
+  /* unless the function is banked.      */
+  for (; p; p = p->next)
     {
       if (!IS_SPEC (p) && DCL_TYPE (p) == UPOINTER)
         DCL_TYPE (p) = port->unqualified_pointer;
       if (IS_PTR (p) && IS_FUNC (p->next))
+        if (!IFFUNC_BANKED(p->next))
         DCL_TYPE (p) = CPOINTER;
     }
 }
@@ -1536,7 +1565,7 @@ checkDecl (symbol * sym, int isProto)
 {
 
   checkSClass (sym, isProto);           /* check the storage class      */
-  changePointer (sym);          /* change pointers if required */
+  changePointer (sym->type);          /* change pointers if required */
 
   /* if this is an array without any dimension
      then update the dimension from the initial value */
@@ -1567,7 +1596,6 @@ copyLinkChain (sym_link * p)
   return head;
 }
 
-
 /*------------------------------------------------------------------*/
 /* cleanUpBlock - cleansup the symbol table specified for all the   */
 /*                symbols in the given block                        */
@@ -1887,6 +1915,16 @@ compareType (sym_link * dest, sym_link * src)
     {
       if (IS_DECL (src))
         {
+          /* banked function pointer */
+          if (IS_GENPTR (dest) && IS_GENPTR (src))
+            {
+              if (IS_FUNC (src->next) && IS_VOID(dest->next))
+                return -1;
+              if (IS_FUNC (dest->next) && IS_VOID(src->next))
+                return -1;
+              return compareType (dest->next, src->next);
+            }
+
           if (DCL_TYPE (src) == DCL_TYPE (dest)) {
             if (IS_FUNC(src)) {
               //checkFunction(src,dest);
@@ -1894,9 +1932,12 @@ compareType (sym_link * dest, sym_link * src)
             return compareType (dest->next, src->next);
           }
           if (IS_PTR (dest) && IS_GENPTR (src) && IS_VOID(src->next)) {
-            return 1;
+            return -1;
           }
-          if (IS_PTR (src) && IS_GENPTR (dest))
+          if (IS_PTR (src) && 
+              (IS_GENPTR (dest) ||
+               ((DCL_TYPE(src) == POINTER) && (DCL_TYPE(dest) == IPOINTER))
+             ))
             return -1;
           if (IS_PTR (dest) && IS_ARRAY (src)) {
             value *val=aggregateToPointer (valFromType(src));
@@ -2291,6 +2332,12 @@ checkFunction (symbol * sym, symbol *csym)
       }
     }
 
+  if (IFFUNC_ISSHADOWREGS(sym->type) && !FUNC_ISISR (sym->type))
+    {
+      werror (E_SHADOWREGS_NO_ISR, sym->name);
+    }
+
+
   for (argCnt=1, acargs = FUNC_ARGS(sym->type); 
        acargs; 
        acargs=acargs->next, argCnt++) {
@@ -2335,7 +2382,10 @@ checkFunction (symbol * sym, symbol *csym)
       werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt");
     }
 
-  if (FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type))
+  /* I don't think this is necessary for interrupts. An isr is a  */
+  /* root in the calling tree.                                    */
+  if ((FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type)) &&
+      (!FUNC_ISISR (sym->type)))
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "using");
     }
@@ -2344,7 +2394,7 @@ checkFunction (symbol * sym, symbol *csym)
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "_naked");
     }
-  
+
   /* Really, reentrant should match regardless of argCnt, but     */
   /* this breaks some existing code (the fp lib functions). If    */
   /* the first argument is always passed the same way, this       */
@@ -2356,6 +2406,17 @@ checkFunction (symbol * sym, symbol *csym)
       werror (E_PREV_DEF_CONFLICT, csym->name, "reentrant");
     }
 
+  if (IFFUNC_ISWPARAM (csym->type) != IFFUNC_ISWPARAM (sym->type))
+    {
+      werror (E_PREV_DEF_CONFLICT, csym->name, "wparam");
+    }
+
+  if (IFFUNC_ISSHADOWREGS (csym->type) != IFFUNC_ISSHADOWREGS (sym->type))
+    {
+      werror (E_PREV_DEF_CONFLICT, csym->name, "shadowregs");
+    }
+  
+
   /* compare expected args with actual args */
   exargs = FUNC_ARGS(csym->type);
   acargs = FUNC_ARGS(sym->type);
@@ -2472,11 +2533,17 @@ processFuncArgs (symbol * func)
 
   /* reset regparm for the port */
   (*port->reset_regparms) ();
+
   /* if any of the arguments is an aggregate */
   /* change it to pointer to the same type */
   while (val)
     {
-        int argreg = 0;
+      int argreg = 0;
+      char buffer[SDCC_NAME_MAX+1];
+      
+      SNPRINTF (buffer, sizeof(buffer), "%s parameter %d", func->name, pNum);
+      checkTypeSanity (val->etype, buffer);
+      
       /* mark it as a register parameter if
          the function does not have VA_ARG
          and as port dictates */
@@ -2524,7 +2591,10 @@ processFuncArgs (symbol * func)
           SNPRINTF (val->name, sizeof(val->name), 
                     "_%s_PARM_%d", func->name, pNum++);
           val->sym = newSymbol (val->name, 1);
-          SPEC_OCLS (val->etype) = port->mem.default_local_map;
+          if (SPEC_SCLS(val->etype) == S_BIT)
+            SPEC_OCLS (val->etype) = bit;
+          else
+            SPEC_OCLS (val->etype) = port->mem.default_local_map;
           val->sym->type = copyLinkChain (val->type);
           val->sym->etype = getSpec (val->sym->type);
           val->sym->_isparm = 1;
@@ -2536,7 +2606,7 @@ processFuncArgs (symbol * func)
               SPEC_STAT (func->etype);
           }
           #endif
-          addSymChain (val->sym);
+          addSymChain (&val->sym);
 
         }
       else                      /* symbol name given create synth name */
@@ -2545,8 +2615,11 @@ processFuncArgs (symbol * func)
           SNPRINTF (val->name, sizeof(val->name), "_%s_PARM_%d", func->name, pNum++);
           strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname));
           val->sym->_isparm = 1;
-          SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
-            (options.model != MODEL_SMALL ? xdata : data);
+          if (SPEC_SCLS(val->etype) == S_BIT)
+            SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = bit;
+          else
+            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 */