* use dynamic memory buffers instead temporary files
[fw/sdcc] / src / SDCCsymt.c
index 40e1fed661ed02d3e1d3172c0342813453db5a8c..d9ca91a14b29a6d8f8eb3bbe997bfa4aeb197c10 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "common.h"
 #include "newalloc.h"
+#include "dbuf_string.h"
 
 #include "SDCCsymt.h"
 
@@ -438,6 +439,7 @@ pointerTypes (sym_link * ptr, sym_link * type)
 void 
 addDecl (symbol * sym, int type, sym_link * p)
 {
+  static sym_link *empty = NULL;
   sym_link *head;
   sym_link *tail;
   sym_link *t;
@@ -445,6 +447,9 @@ addDecl (symbol * sym, int type, sym_link * p)
   if (getenv("SDCC_DEBUG_FUNCTION_POINTERS"))
     fprintf (stderr, "SDCCsymt.c:addDecl(%s,%d,%p)\n", sym->name, type, p);
 
+  if (empty == NULL)
+    empty = newLink(SPECIFIER);
+
   /* if we are passed a link then set head & tail */
   if (p)
     {
@@ -464,28 +469,28 @@ addDecl (symbol * sym, int type, sym_link * p)
       sym->type = head;
       sym->etype = tail;
     }
+  else if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail)
+    {
+      sym->etype = mergeSpec (sym->etype, head, sym->name);
+    }
+  else if (IS_SPEC (sym->etype) && !IS_SPEC (head) && head == tail)
+    {
+      t = sym->type;
+      while (t->next != sym->etype)
+        t = t->next;
+      t->next = head;
+      tail->next = sym->etype;
+    }
+  else if (IS_FUNC (sym->type) && IS_SPEC (sym->type->next) &&
+           !memcmp(sym->type->next, empty, sizeof(sym_link)))
+    {
+      sym->type->next = head;
+      sym->etype = tail;
+    }
   else
     {
-      if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail)
-        {
-          sym->etype = mergeSpec (sym->etype, head, sym->name);
-        }
-      else
-        {
-          if (IS_SPEC (sym->etype) && !IS_SPEC (head) && head == tail)
-            {
-              t = sym->type;
-              while (t->next != sym->etype)
-                t = t->next;
-              t->next = head;
-              tail->next = sym->etype;
-            }
-          else
-            {
-              sym->etype->next = head;
-              sym->etype = tail;
-            }
-        }
+      sym->etype->next = head;
+      sym->etype = tail;
     }
 
   /* if the type is an unknown pointer and has
@@ -653,6 +658,7 @@ mergeSpec (sym_link * dest, sym_link * src, char *name)
   SPEC_CONST(dest) |= SPEC_CONST (src);
   SPEC_ABSA (dest) |= SPEC_ABSA (src);
   SPEC_VOLATILE (dest) |= SPEC_VOLATILE (src);
+  SPEC_RESTRICT (dest) |= SPEC_RESTRICT (src);
   SPEC_ADDR (dest) |= SPEC_ADDR (src);
   SPEC_OCLS (dest) = SPEC_OCLS (src);
   SPEC_BLEN (dest) |= SPEC_BLEN (src);
@@ -1428,8 +1434,7 @@ checkSClass (symbol * sym, int isProto)
     fprintf (stderr, "checkSClass: %s \n", sym->name);
   }
   
-  /* type is literal can happen for enums change
-     to auto */
+  /* type is literal can happen for enums change to auto */
   if (SPEC_SCLS (sym->etype) == S_LITERAL && !SPEC_ENUM (sym->etype))
     SPEC_SCLS (sym->etype) = S_AUTO;
   
@@ -1440,6 +1445,24 @@ checkSClass (symbol * sym, int isProto)
       SPEC_VOLATILE (sym->etype) = 1;
     }
   
+  /* make sure restrict is only used with pointers */
+  if (SPEC_RESTRICT (sym->etype))
+    {
+      werrorfl (sym->fileDef, sym->lineDef, E_BAD_RESTRICT);
+      SPEC_RESTRICT (sym->etype) = 0;
+    }
+  t = sym->type;
+  while (t)
+    {
+      if (IS_DECL (t) && DCL_PTR_RESTRICT (t) && !IS_PTR (t))
+        {
+          werrorfl (sym->fileDef, sym->lineDef, E_BAD_RESTRICT);
+         DCL_PTR_RESTRICT (t) = 0;
+          break;
+        }
+      t = t->next;
+    }
+  
   /* if absolute address given then it mark it as
      volatile -- except in the PIC port */
 
@@ -1588,6 +1611,7 @@ checkSClass (symbol * sym, int isProto)
         //!sym->level &&
         port->mem.code_ro &&
         !IS_EXTERN (sym->etype) &&
+        !SPEC_ABSA (sym->etype) &&
         !funcInChain (sym->type))
       werror (E_CODE_NO_INIT, sym->name);
   }
@@ -1966,12 +1990,12 @@ computeType (sym_link * type1, sym_link * type2,
       && (   (SPEC_USIGN (etype1)
               /* if this operand is promoted to a larger type,
                  then it will be promoted to a signed type */
-              && !(getSize (etype1) < getSize (reType))
+              && !(bitsForType (etype1) < bitsForType (reType))
               /* char require special handling */
               && !IS_CHAR (etype1))
           || /* same for 2nd operand */  
              (SPEC_USIGN (etype2)
-              && !(getSize (etype2) < getSize (reType))
+              && !(bitsForType (etype2) < bitsForType (reType))
               && !IS_CHAR (etype2))
           || /* if both are 'unsigned char' and not promoted
                 let the result be unsigned too */
@@ -2772,10 +2796,8 @@ void PT(sym_link *type)
 void
 printTypeChain (sym_link * start, FILE * of)
 {
+  struct dbuf_s dbuf;
   int nlr = 0;
-  value *args;
-  sym_link * type, * search;
-  STORAGE_CLASS scls;
 
   if (!of)
     {
@@ -2783,8 +2805,23 @@ printTypeChain (sym_link * start, FILE * of)
       nlr = 1;
     }
 
+  dbuf_init (&dbuf, 1024);
+  dbuf_printTypeChain (start, &dbuf);
+  dbuf_write_and_destroy (&dbuf, of);
+
+  if (nlr)
+    putc ('\n', of);
+}
+
+void
+dbuf_printTypeChain (sym_link * start, struct dbuf_s *dbuf)
+{
+  value *args;
+  sym_link * type, * search;
+  STORAGE_CLASS scls;
+
   if (start==NULL) {
-    fprintf (of, "void");
+    dbuf_append_str (dbuf, "void");
     return;
   }
 
@@ -2804,18 +2841,18 @@ printTypeChain (sym_link * start, FILE * of)
       if (type==start) {
         switch (scls) 
           {
-          case S_DATA: fprintf (of, "data-"); break;
-          case S_XDATA: fprintf (of, "xdata-"); break;
-          case S_SFR: fprintf (of, "sfr-"); break;
-          case S_SBIT: fprintf (of, "sbit-"); break;
-          case S_CODE: fprintf (of, "code-"); break;
-          case S_IDATA: fprintf (of, "idata-"); break;
-          case S_PDATA: fprintf (of, "pdata-"); break;
-          case S_LITERAL: fprintf (of, "literal-"); break;
-          case S_STACK: fprintf (of, "stack-"); break;
-          case S_XSTACK: fprintf (of, "xstack-"); break;
-          case S_BIT: fprintf (of, "bit-"); break;
-          case S_EEPROM: fprintf (of, "eeprom-"); break;
+          case S_DATA: dbuf_append_str (dbuf, "data-"); break;
+          case S_XDATA: dbuf_append_str (dbuf, "xdata-"); break;
+          case S_SFR: dbuf_append_str (dbuf, "sfr-"); break;
+          case S_SBIT: dbuf_append_str (dbuf, "sbit-"); break;
+          case S_CODE: dbuf_append_str (dbuf, "code-"); break;
+          case S_IDATA: dbuf_append_str (dbuf, "idata-"); break;
+          case S_PDATA: dbuf_append_str (dbuf, "pdata-"); break;
+          case S_LITERAL: dbuf_append_str (dbuf, "literal-"); break;
+          case S_STACK: dbuf_append_str (dbuf, "stack-"); break;
+          case S_XSTACK: dbuf_append_str (dbuf, "xstack-"); break;
+          case S_BIT: dbuf_append_str (dbuf, "bit-"); break;
+          case S_EEPROM: dbuf_append_str (dbuf, "eeprom-"); break;
           default: break;
           }
       }
@@ -2824,57 +2861,57 @@ printTypeChain (sym_link * start, FILE * of)
         {
           if (!IS_FUNC(type)) {
             if (DCL_PTR_VOLATILE (type)) {
-              fprintf (of, "volatile-");
+              dbuf_append_str (dbuf, "volatile-");
             }
             if (DCL_PTR_CONST (type)) {
-              fprintf (of, "const-");
+              dbuf_append_str (dbuf, "const-");
             }
           }
           switch (DCL_TYPE (type))
             {
             case FUNCTION:
-              fprintf (of, "function %s %s", 
+              dbuf_printf (dbuf, "function %s %s", 
                        (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "),
                        (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " "));
-              fprintf (of, "( ");
+              dbuf_append_str (dbuf, "( ");
               for (args = FUNC_ARGS(type); 
                    args; 
                    args=args->next) {
-                printTypeChain(args->type, of);
+                dbuf_printTypeChain(args->type, dbuf);
                 if (args->next)
-                  fprintf(of, ", ");
+                  dbuf_append_str (dbuf, ", ");
               }
-              fprintf (of, ") ");
+              dbuf_append_str (dbuf, ") ");
               break;
             case GPOINTER:
-              fprintf (of, "generic* ");
+              dbuf_append_str (dbuf, "generic* ");
               break;
             case CPOINTER:
-              fprintf (of, "code* ");
+              dbuf_append_str (dbuf, "code* ");
               break;
             case FPOINTER:
-              fprintf (of, "xdata* ");
+              dbuf_append_str (dbuf, "xdata* ");
               break;
             case EEPPOINTER:
-              fprintf (of, "eeprom* ");
+              dbuf_append_str (dbuf, "eeprom* ");
               break;
             case POINTER:
-              fprintf (of, "near* ");
+              dbuf_append_str (dbuf, "near* ");
               break;
             case IPOINTER:
-              fprintf (of, "idata* ");
+              dbuf_append_str (dbuf, "idata* ");
               break;
             case PPOINTER:
-              fprintf (of, "pdata* ");
+              dbuf_append_str (dbuf, "pdata* ");
               break;
             case UPOINTER:
-              fprintf (of, "unknown* ");
+              dbuf_append_str (dbuf, "unknown* ");
               break;
             case ARRAY:
               if (DCL_ELEM(type)) {
-                fprintf (of, "[%d] ", DCL_ELEM(type));
+                dbuf_printf (dbuf, "[%d] ", DCL_ELEM(type));
               } else {
-                fprintf (of, "[] ");
+                dbuf_append_str (dbuf, "[] ");
               }
               break;
             }
@@ -2882,57 +2919,57 @@ printTypeChain (sym_link * start, FILE * of)
       else
         {
           if (SPEC_VOLATILE (type))
-            fprintf (of, "volatile-");
+            dbuf_append_str (dbuf, "volatile-");
           if (SPEC_CONST (type))
-            fprintf (of, "const-");
+            dbuf_append_str (dbuf, "const-");
           if (SPEC_USIGN (type))
-            fprintf (of, "unsigned-");
+            dbuf_append_str (dbuf, "unsigned-");
           switch (SPEC_NOUN (type))
             {
             case V_INT:
               if (IS_LONG (type))
-                fprintf (of, "long-");
-              fprintf (of, "int");
+                dbuf_append_str (dbuf, "long-");
+              dbuf_append_str (dbuf, "int");
               break;
 
             case V_CHAR:
-              fprintf (of, "char");
+              dbuf_append_str (dbuf, "char");
               break;
 
             case V_VOID:
-              fprintf (of, "void");
+              dbuf_append_str (dbuf, "void");
               break;
 
             case V_FLOAT:
-              fprintf (of, "float");
+              dbuf_append_str (dbuf, "float");
               break;
 
             case V_FIXED16X16:
-              fprintf (of, "fixed16x16");
+              dbuf_append_str (dbuf, "fixed16x16");
               break;
 
             case V_STRUCT:
-              fprintf (of, "struct %s", SPEC_STRUCT (type)->tag);
+              dbuf_printf (dbuf, "struct %s", SPEC_STRUCT (type)->tag);
               break;
 
             case V_SBIT:
-              fprintf (of, "sbit");
+              dbuf_append_str (dbuf, "sbit");
               break;
 
             case V_BIT:
-              fprintf (of, "bit");
+              dbuf_append_str (dbuf, "bit");
               break;
 
             case V_BITFIELD:
-              fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
+              dbuf_printf (dbuf, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
               break;
 
             case V_DOUBLE:
-              fprintf (of, "double");
+              dbuf_append_str (dbuf, "double");
               break;
 
             default:
-              fprintf (of, "unknown type");
+              dbuf_append_str (dbuf, "unknown type");
               break;
             }
         }
@@ -2941,10 +2978,8 @@ printTypeChain (sym_link * start, FILE * of)
         search = search->next;
       type = search;
       if (type)
-        fputc (' ', of);
+          dbuf_append_char(dbuf, ' ');
     }
-  if (nlr)
-    fprintf (of, "\n");
 }
 
 /*--------------------------------------------------------------------*/
@@ -3126,7 +3161,7 @@ printTypeChainRaw (sym_link * start, FILE * of)
 /* powof2 - returns power of two for the number if number is pow 2 */
 /*-----------------------------------------------------------------*/
 int
-powof2 (TYPE_UDWORD num)
+powof2 (TYPE_TARGET_ULONG num)
 {
   int nshifts = 0;
   int n1s = 0;
@@ -3457,17 +3492,50 @@ initCSupport ()
         {
           for (muldivmod = 1; muldivmod < 3; muldivmod++)
             {
-              /* div and mod */
-              SNPRINTF (buffer, sizeof(buffer),
-                        "_%s%s%s",
-                       smuldivmod[muldivmod],
-                       ssu[su],
-                       sbwd[bwd]);
-              __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
-              FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+              /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */
+             if (!TARGET_IS_PIC16 || muldivmod != 1 || bwd != 0 || su != 0)
+             {
+               SNPRINTF (buffer, sizeof(buffer),
+                   "_%s%s%s",
+                   smuldivmod[muldivmod],
+                   ssu[su],
+                   sbwd[bwd]);
+               __muldiv[muldivmod][bwd][su] = funcOfType (
+                   _mangleFunctionName(buffer),
+                   __multypes[bwd][su],
+                   __multypes[bwd][su],
+                   2,
+                   options.intlong_rent);
+               FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+             }
             }
         }
     }
+
+  if (TARGET_IS_PIC16)
+  {
+    /* PIC16 port wants __divschar/__modschar to return an int, so that both
+     * 100 / -4 = -25 and -128 / -1 = 128 can be handled correctly
+     * (first one would have to be sign extended, second one must not be).
+     * Similarly, modschar should be handled, but the iCode introduces cast
+     * here and forces '% : s8 x s8 -> s8' ... */
+    su = 0; bwd = 0;
+    for (muldivmod = 1; muldivmod < 2; muldivmod++) {
+      SNPRINTF (buffer, sizeof(buffer),
+         "_%s%s%s",
+         smuldivmod[muldivmod],
+         ssu[su],
+         sbwd[bwd]);
+      __muldiv[muldivmod][bwd][su] = funcOfType (
+         _mangleFunctionName(buffer),
+         __multypes[1][su],
+         __multypes[bwd][su],
+         2,
+         options.intlong_rent);
+      FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+    }
+  }
+
   /* mul only */
   muldivmod = 0;
   /* byte */
@@ -3552,7 +3620,7 @@ sym_link *validateLink(sym_link         *l,
             " expected %s, got %s\n",
             macro, args, file, line, 
             DECLSPEC2TXT(select), l ? DECLSPEC2TXT(l->class) : "null-link");
-    exit(-1);
+    exit(EXIT_FAILURE);
     return l; // never reached, makes compiler happy.
 }