* src/SDCCsymt.c (initCSupport): fix compile warning on Cygwin
[fw/sdcc] / src / SDCCsymt.c
index be8444e8cfef6957cd3e854f31d718e69a685f2c..ed9c4fb5bfef072be5a6be12c3b4123861881872 100644 (file)
@@ -115,11 +115,13 @@ addSym (bucket ** stab,
   bucket *bp;                  /* temp bucket    *         */
 
   if (checkType) {
+    symbol *csym = (symbol *)sym;
+
     if (getenv("DEBUG_SANITY")) {
       fprintf (stderr, "addSym: %s ", sname);
     }
     /* make sure the type is complete and sane */
-    checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
+    checkTypeSanity(csym->etype, csym->name);
   }
 
   /* prevent overflow of the (r)name buffers */
@@ -369,7 +371,7 @@ pointerTypes (sym_link * ptr, sym_link * type)
          DCL_TYPE (ptr) = EEPPOINTER;
          break;
        default:
-         DCL_TYPE (ptr) = GPOINTER;
+         DCL_TYPE (ptr) = port->unqualified_pointer;
          break;
        }
       /* the storage class of type ends here */
@@ -383,7 +385,7 @@ pointerTypes (sym_link * ptr, sym_link * type)
   while (ptr)
     {
       if (!IS_SPEC (ptr) && DCL_TYPE (ptr) == UPOINTER)
-       DCL_TYPE (ptr) = GPOINTER;
+       DCL_TYPE (ptr) = port->unqualified_pointer;
       ptr = ptr->next;
     }
 
@@ -392,7 +394,7 @@ pointerTypes (sym_link * ptr, sym_link * type)
   while (type)
     {
       if (!IS_SPEC (type) && DCL_TYPE (type) == UPOINTER)
-       DCL_TYPE (type) = GPOINTER;
+       DCL_TYPE (type) = port->unqualified_pointer;
       type = type->next;
     }
 
@@ -408,6 +410,9 @@ addDecl (symbol * sym, int type, sym_link * p)
   sym_link *tail;
   sym_link *t;
 
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "SDCCsymt.c:addDecl(%s,%d,%p)\n", sym->name, type, p);
+
   /* if we are passed a link then set head & tail */
   if (p)
     {
@@ -470,6 +475,12 @@ addDecl (symbol * sym, int type, sym_link * p)
       SPEC_VOLATILE (sym->etype) = SPEC_VOLATILE (DCL_TSPEC (p));
       DCL_TSPEC (p) = NULL;
     }
+
+  // if there is a function in this type chain
+  if (p && funcInChain(sym->type)) {
+    processFuncArgs (sym);
+  }
+
   return;
 }
 
@@ -610,7 +621,10 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
   SPEC_BLEN (dest) |= SPEC_BLEN (src);
   SPEC_BSTR (dest) |= SPEC_BSTR (src);
   SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
-
+  SPEC_ENUM (dest) |= SPEC_ENUM (src);
+  if (SPEC_ARGREG(src) && !SPEC_ARGREG(dest))
+      SPEC_ARGREG(dest) = SPEC_ARGREG(src);
+  
   if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
     SPEC_STRUCT (dest) = SPEC_STRUCT (src);
 
@@ -622,6 +636,9 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
   FUNC_ISREENT(dest) |= FUNC_ISREENT(src);
   FUNC_ISNAKED(dest) |= FUNC_ISNAKED(src);
   FUNC_ISISR(dest) |= FUNC_ISISR(src);
+  FUNC_ISJAVANATIVE(dest) |= FUNC_ISJAVANATIVE(src);
+  FUNC_ISBUILTIN(dest) |= FUNC_ISBUILTIN(src);
+  FUNC_ISOVERLAY(dest) |= FUNC_ISOVERLAY(src);
   FUNC_INTNO(dest) |= FUNC_INTNO(src);
   FUNC_REGBANK(dest) |= FUNC_REGBANK(src);
 
@@ -771,10 +788,14 @@ getSize (sym_link * p)
   /* this is a specifier  */
   switch (DCL_TYPE (p))
     {
-    case FUNCTION:
-      return 2;
     case ARRAY:
-      return DCL_ELEM (p) * getSize (p->next);
+      if (DCL_ELEM(p)) {
+       return DCL_ELEM (p) * getSize (p->next);
+      } else {
+         //    werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+         //    "can not tell the size of an array[]");
+       return 0;
+      }
     case IPOINTER:
     case PPOINTER:
     case POINTER:
@@ -782,6 +803,7 @@ getSize (sym_link * p)
     case EEPPOINTER:
     case FPOINTER:
     case CPOINTER:
+    case FUNCTION:
       return (FPTRSIZE);
     case GPOINTER:
       return (GPTRSIZE);
@@ -830,8 +852,6 @@ bitsForType (sym_link * p)
   /* this is a specifier  */
   switch (DCL_TYPE (p))
     {
-    case FUNCTION:
-      return 2;
     case ARRAY:
       return DCL_ELEM (p) * getSize (p->next) * 8;
     case IPOINTER:
@@ -841,6 +861,7 @@ bitsForType (sym_link * p)
     case EEPPOINTER:
     case FPOINTER:
     case CPOINTER:
+    case FUNCTION:
       return (FPTRSIZE * 8);
     case GPOINTER:
       return (GPTRSIZE * 8);
@@ -971,6 +992,7 @@ addSymChain (symbol * symHead)
          }
          /* delete current entry */
          deleteSym (SymbolTab, csym, csym->name);
+         deleteFromSeg(csym);
        } else {
          /* not extern */
          werror (E_DUPLICATE, sym->name);
@@ -1009,25 +1031,27 @@ structElemType (sym_link * stype, value * id)
   sym_link *type, *etype;
   sym_link *petype = getSpec (stype);
 
-  if (!fields || !id)
-    return NULL;
+  if (fields && id) {
+    
+    /* look for the id */
+    while (fields)
+      {
+       if (strcmp (fields->rname, id->name) == 0)
+         {
+           type = copyLinkChain (fields->type);
+           etype = getSpec (type);
+           SPEC_SCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ?
+                                SPEC_SCLS (etype) : SPEC_SCLS (petype));
+           return type;
+         }
+       fields = fields->next;
+      }
+  }
 
-  /* look for the id */
-  while (fields)
-    {
-      if (strcmp (fields->rname, id->name) == 0)
-       {
-         type = copyLinkChain (fields->type);
-         etype = getSpec (type);
-         SPEC_SCLS (etype) = (SPEC_SCLS (petype) == S_REGISTER ?
-                              SPEC_SCLS (etype) : SPEC_SCLS (petype));
-         return type;
-       }
-      fields = fields->next;
-    }
   werror (E_NOT_MEMBER, id->name);
-
-  return NULL;
+    
+  // the show must go on
+  return newIntLink();
 }
 
 /*------------------------------------------------------------------*/
@@ -1097,11 +1121,6 @@ compStructSize (int su, structdef * sdef)
            sum += getSize (loop->type);
        }
 
-       /* if function then do the arguments for it */
-       if (funcInChain (loop->type)) {
-           processFuncArgs (loop, 1);
-       }
-
        loop = loop->next;
 
        /* if this is not a bitfield but the */
@@ -1154,13 +1173,22 @@ checkSClass (symbol * sym, int isProto)
     }
   
   /* if absolute address given then it mark it as
-     volatile */
-  if (IS_ABSOLUTE (sym->etype))
-    SPEC_VOLATILE (sym->etype) = 1;
+     volatile -- except in the PIC port */
+
+#if !OPT_DISABLE_PIC
+  /* The PIC port uses a different peep hole optimizer based on "pCode" */
+  if (!TARGET_IS_PIC)
+#endif
+
+    if (IS_ABSOLUTE (sym->etype))
+      SPEC_VOLATILE (sym->etype) = 1;
   
+
   /* global variables declared const put into code */
+  /* if no other storage class specified */
   if (sym->level == 0 &&
-      SPEC_CONST (sym->etype)) {
+      SPEC_CONST (sym->etype) &&
+      SPEC_SCLS(sym->etype) == S_FIXED) {
     SPEC_SCLS (sym->etype) = S_CODE;
   }
   
@@ -1282,7 +1310,7 @@ changePointer (symbol * sym)
   for (p = sym->type; p; p = p->next)
     {
       if (!IS_SPEC (p) && DCL_TYPE (p) == UPOINTER)
-       DCL_TYPE (p) = GPOINTER;
+       DCL_TYPE (p) = port->unqualified_pointer;
       if (IS_PTR (p) && IS_FUNC (p->next))
        DCL_TYPE (p) = CPOINTER;
     }
@@ -1399,11 +1427,11 @@ computeType (sym_link * type1, sym_link * type2)
   else if (IS_BITVAR (etype2) && !IS_BITVAR (etype1))
     rType = copyLinkChain (type1);
   else
-    /* if one of them is a pointer then that
+    /* if one of them is a pointer or array then that
        prevails */
-  if (IS_PTR (type1))
+  if (IS_PTR (type1) || IS_ARRAY (type1))
     rType = copyLinkChain (type1);
-  else if (IS_PTR (type2))
+  else if (IS_PTR (type2) || IS_ARRAY (type2))
     rType = copyLinkChain (type2);
   else if (getSize (type1) > getSize (type2))
     rType = copyLinkChain (type1);
@@ -1530,6 +1558,7 @@ inCalleeSaveList (char *s)
 {
   int i;
 
+  if (options.all_callee_saves) return 1;
   for (i = 0; options.calleeSaves[i]; i++)
     if (strcmp (options.calleeSaves[i], s) == 0)
       return 1;
@@ -1571,23 +1600,26 @@ aggregateToPointer (value * val)
        case S_FIXED:
          if (SPEC_OCLS(val->etype)) {
            DCL_TYPE(val->type)=PTR_TYPE(SPEC_OCLS(val->etype));
-           break;
-         }
-
-         if (TARGET_IS_DS390)
-           {
+         } else {
+#if 1
+           // this happens for (external) function parameters
+           DCL_TYPE (val->type) = port->unqualified_pointer;
+#else
+           if (TARGET_IS_DS390) {
              /* The AUTO and REGISTER classes should probably
               * also become generic pointers, but I haven't yet
               * devised a test case for that.
               */
-             DCL_TYPE (val->type) = GPOINTER;
+             DCL_TYPE (val->type) = port->unqualified_pointer;
              break;
            }
-         if (options.model==MODEL_LARGE) {
-           DCL_TYPE (val->type) = FPOINTER;
-           break;
+           if (options.model==MODEL_LARGE) {
+             DCL_TYPE (val->type) = FPOINTER;
+             break;
+           }
+#endif
          }
-         /* fall through! */
+         break;
        case S_AUTO:
        case S_DATA:
        case S_REGISTER:
@@ -1603,7 +1635,7 @@ aggregateToPointer (value * val)
          DCL_TYPE (val->type) = EEPPOINTER;
          break;
        default:
-         DCL_TYPE (val->type) = GPOINTER;
+         DCL_TYPE (val->type) = port->unqualified_pointer;
        }
       
       /* is there is a symbol associated then */
@@ -1657,7 +1689,7 @@ checkFunction (symbol * sym, symbol *csym)
 
   /* check if this function is defined as calleeSaves
      then mark it as such */
-    FUNC_CALLEESAVES(sym->type) = inCalleeSaveList (sym->name);
+  FUNC_CALLEESAVES(sym->type) = inCalleeSaveList (sym->name);
 
   /* if interrupt service routine  */
   /* then it cannot have arguments */
@@ -1669,6 +1701,26 @@ checkFunction (symbol * sym, symbol *csym)
       }
     }
 
+  for (argCnt=1, acargs = FUNC_ARGS(sym->type); 
+       acargs; 
+       acargs=acargs->next, argCnt++) {
+    if (!acargs->sym) { 
+      // this can happen for reentrant functions
+      werror(E_PARAM_NAME_OMITTED, sym->name, argCnt);
+      // the show must go on: synthesize a name and symbol
+      sprintf (acargs->name, "_%s_PARM_%d", sym->name, argCnt);
+      acargs->sym = newSymbol (acargs->name, 1);
+      SPEC_OCLS (acargs->etype) = istack;
+      acargs->sym->type = copyLinkChain (acargs->type);
+      acargs->sym->etype = getSpec (acargs->sym->type);
+      acargs->sym->_isparm = 1;
+      strcpy (acargs->sym->rname, acargs->name);
+    } else if (strcmp(acargs->sym->name, acargs->sym->rname)==0) { 
+      // synthesized name
+      werror(E_PARAM_NAME_OMITTED, sym->name, argCnt);
+    }
+  }
+
   if (!csym && !(csym = findSym (SymbolTab, sym, sym->name)))
     return 1;                  /* not defined nothing more to check  */
 
@@ -1747,6 +1799,7 @@ checkFunction (symbol * sym, symbol *csym)
   /* replace with this defition */
   sym->cdef = csym->cdef;
   deleteSym (SymbolTab, csym, csym->name);
+  deleteFromSeg(csym);
   addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
   if (IS_EXTERN (csym->etype) && !
       IS_EXTERN (sym->etype))
@@ -1760,20 +1813,23 @@ checkFunction (symbol * sym, symbol *csym)
 /* processFuncArgs - does some processing with function args       */
 /*-----------------------------------------------------------------*/
 void 
-processFuncArgs (symbol * func, int ignoreName)
+processFuncArgs (symbol * func)
 {
   value *val;
   int pNum = 1;
   sym_link *funcType=func->type;
 
+  if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
+    fprintf (stderr, "SDCCsymt.c:processFuncArgs(%s)\n", func->name);
+
   // if this is a pointer to a function
-  if (DCL_TYPE(funcType)==CPOINTER) {
+  if (IS_PTR(funcType)) {
     funcType=funcType->next;
   }
 
   /* if this function has variable argument list */
   /* then make the function a reentrant one    */
-  if (IFFUNC_HASVARARGS(funcType))
+  if (IFFUNC_HASVARARGS(funcType) || (options.stackAuto && !func->cdef))
     FUNC_ISREENT(funcType)=1;
 
   /* check if this function is defined as calleeSaves
@@ -1796,19 +1852,24 @@ processFuncArgs (symbol * func, int ignoreName)
   /* change it to pointer to the same type */
   while (val)
     {
+       int argreg = 0;
       /* mark it as a register parameter if
          the function does not have VA_ARG
          and as port dictates */
       if (!IFFUNC_HASVARARGS(funcType) &&
-         (*port->reg_parm) (val->type))
+         (argreg = (*port->reg_parm) (val->type)))
        {
          SPEC_REGPARM (val->etype) = 1;
+         SPEC_ARGREG(val->etype) = argreg;
+       } else if (IFFUNC_ISREENT(funcType)) {
+           FUNC_HASSTACKPARM(funcType) = 1;
        }
 
       if (IS_AGGREGATE (val->type))
        {
          aggregateToPointer (val);
        }
+
       val = val->next;
       pNum++;
     }
@@ -1836,7 +1897,6 @@ processFuncArgs (symbol * func, int ignoreName)
       /* synthesize a variable name */
       if (!val->sym)
        {
-
          sprintf (val->name, "_%s_PARM_%d", func->name, pNum++);
          val->sym = newSymbol (val->name, 1);
          SPEC_OCLS (val->etype) = port->mem.default_local_map;
@@ -1906,7 +1966,7 @@ printTypeChain (sym_link * start, FILE * of)
     }
 
   if (start==NULL) {
-    fprintf (of, "**err**");
+    fprintf (of, "void");
     return;
   }
 
@@ -1924,51 +1984,57 @@ printTypeChain (sym_link * start, FILE * of)
          switch (DCL_TYPE (type))
            {
            case FUNCTION:
-             fprintf (of, "function ");
+             fprintf (of, "function %s %s", 
+                      (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "),
+                      (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " "));
              break;
            case GPOINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* generic ");
+             fprintf (of, "generic * ");
              break;
            case CPOINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* code ");
+             fprintf (of, "code * ");
              break;
            case FPOINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* xdata ");
+             fprintf (of, "xdata * ");
              break;
            case EEPPOINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* eeprom ");
+             fprintf (of, "eeprom * ");
              break;
 
            case POINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* near ");
+             fprintf (of, "near *");
              break;
            case IPOINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* idata ");
+             fprintf (of, "idata * ");
              break;
            case PPOINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* pdata ");
+             fprintf (of, "pdata * ");
              break;
            case UPOINTER:
              if (DCL_PTR_CONST (type))
                fprintf (of, "const ");
-             fprintf (of, "* unkown ");
+             fprintf (of, "unkown * ");
              break;
            case ARRAY:
-             fprintf (of, "[] ");
+             if (DCL_ELEM(type)) {
+               fprintf (of, "[%d] ", DCL_ELEM(type));
+             } else {
+               fprintf (of, "[] ");
+             }
              break;
            }
        }
@@ -1997,7 +2063,6 @@ printTypeChain (sym_link * start, FILE * of)
            fprintf (of, "unsigned ");
          if (SPEC_CONST (type))
            fprintf (of, "const ");
-
          switch (SPEC_NOUN (type))
            {
            case V_INT:
@@ -2308,6 +2373,111 @@ _mangleFunctionName(char *in)
     }
 }
 
+/*-----------------------------------------------------------------*/
+/* typeFromStr - create a typechain from an encoded string         */
+/* basic types -       'c' - char                                 */
+/*                     's' - short                                */
+/*                     'i' - int                                  */
+/*                     'l' - long                                 */
+/*                      'f' - float                               */
+/*                      'v' - void                                */
+/*                      '*' - pointer - default (GPOINTER)        */
+/* modifiers -          'u' - unsigned                             */
+/* pointer modifiers -  'g' - generic                              */
+/*                      'x' - xdata                                */
+/*                      'p' - code                                 */
+/*                      'd' - data                                 */                     
+/*                      'F' - function                             */                     
+/* examples : "ig*" - generic int *                               */
+/*            "cx*" - char xdata *                                 */
+/*            "ui" -  unsigned int                                 */
+/*-----------------------------------------------------------------*/
+sym_link *typeFromStr (char *s)
+{
+    sym_link *r = newLink();
+    int usign = 0;
+
+    do {
+       sym_link *nr;
+       switch (*s) {
+       case 'u' : 
+           usign = 1;
+           s++;
+           continue ;
+           break ;
+       case 'c':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_CHAR;
+           break;
+       case 's':
+       case 'i':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_INT;
+           break;
+       case 'l':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_INT;
+           SPEC_LONG(r) = 1;
+           break;
+       case 'f':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_FLOAT;
+           break;
+       case 'v':
+           r->class = SPECIFIER;
+           SPEC_NOUN(r) = V_VOID;
+           break;
+       case '*':
+           DCL_TYPE(r) = port->unqualified_pointer;
+           break;
+       case 'g':
+       case 'x':
+       case 'p':
+       case 'd':
+       case 'F':
+           assert(*(s+1)=='*');
+           nr = newLink();
+           nr->next = r;
+           r = nr;
+           r->class = DECLARATOR ;
+           switch (*s) {
+           case 'g':
+               DCL_TYPE(r) = GPOINTER;
+               break;
+           case 'x':
+               DCL_TYPE(r) = FPOINTER;
+               break;
+           case 'p':
+               DCL_TYPE(r) = CPOINTER;
+               break;
+           case 'd':
+               DCL_TYPE(r) = POINTER;
+               break;
+           case 'F':
+               DCL_TYPE(r) = FUNCTION;
+               nr = newLink();
+               nr->next = r;
+               r = nr;
+               r->class = DECLARATOR ;
+               DCL_TYPE(r) = CPOINTER;
+               break;
+           }
+           s++;
+           break;
+       default:
+           werror(E_INTERNAL_ERROR, __FILE__, __LINE__, 
+                  "typeFromStr: unknown type");
+           break;
+       }
+       if (IS_SPEC(r) && usign) {
+           SPEC_USIGN(r) = 1;
+           usign = 0;
+       }
+       s++;
+    } while (*s);
+    return r;
+}
+
 /*-----------------------------------------------------------------*/
 /* initCSupport - create functions for C support routines          */
 /*-----------------------------------------------------------------*/
@@ -2342,7 +2512,7 @@ initCSupport ()
 
   for (bwd = 0; bwd < 3; bwd++)
     {
-      sym_link *l;
+      sym_link *l = NULL;
       switch (bwd)
        {
        case 0:
@@ -2382,12 +2552,12 @@ initCSupport ()
              if (tofrom)
                {
                  sprintf (buffer, "__fs2%s%s", ssu[su], sbwd[bwd]);
-                 __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], floatType, 1, options.float_rent);
+                 __conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], floatType, 1, options.float_rent);
                }
              else
                {
                  sprintf (buffer, "__%s%s2fs", ssu[su], sbwd[bwd]);
-                 __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), floatType, __multypes[bwd][su], 1, options.float_rent);
+                 __conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent);
                }
            }
        }
@@ -2425,3 +2595,21 @@ initCSupport ()
        }
     }
 }
+
+/*-----------------------------------------------------------------*/
+/* initBuiltIns - create prototypes for builtin functions          */
+/*-----------------------------------------------------------------*/
+void initBuiltIns()
+{
+    int i;
+    symbol *sym;
+
+    if (!port->builtintable) return ;
+
+    for (i = 0 ; port->builtintable[i].name ; i++) {
+       sym = funcOfTypeVarg(port->builtintable[i].name,port->builtintable[i].rtype,
+                            port->builtintable[i].nParms,port->builtintable[i].parm_types);
+       FUNC_ISBUILTIN(sym->type) = 1;
+       FUNC_ISREENT(sym->type) = 0;    /* can never be reentrant */
+    }
+}