This isn't needed anymore because of SDCCast.c:1.82
[fw/sdcc] / src / SDCCsymt.c
index bf7a5809103e09b0d31a8218d12a69830267e5aa..51702c9e652f4aeef9d3d91a85957bfc77f7c635 100644 (file)
@@ -30,7 +30,7 @@ char *nounName(sym_link *sl) {
     {
     case V_INT: {
       if (SPEC_LONG(sl)) return "long";
-      if (SPEC_SHORT(sl)) return "short";
+      if (sl->select.s._short) return "short";
       return "int";
     }
     case V_FLOAT: return "float";
@@ -98,16 +98,16 @@ addSym (bucket ** stab,
        void *sym,
        char *sname,
        int level,
-       int block)
+       int block,
+       int checkType)
 {
   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) {
+  if (checkType) {
+    if (getenv("DEBUG_SANITY")) {
+      fprintf (stderr, "addSym: %s ", sname);
+    }
     /* make sure the type is complete and sane */
     checkTypeSanity(((symbol *)sym)->etype, ((symbol *)sym)->name);
   }
@@ -217,13 +217,12 @@ findSymWithLevel (bucket ** stab, symbol * sym)
    **/
   while (bp)
     {
-
       if (strcmp (bp->name, sym->name) == 0 && bp->level <= sym->level)
        {
          /* if this is parameter then nothing else need to be checked */
          if (((symbol *) (bp->sym))->_isparm)
            return (bp->sym);
-         /* if levels match then block numbers hsould also match */
+         /* if levels match then block numbers should also match */
          if (bp->level && bp->level == sym->level && bp->block == sym->block)
            return (bp->sym);
          /* if levels don't match then we are okay */
@@ -318,9 +317,13 @@ pointerTypes (sym_link * ptr, sym_link * type)
     ptr = ptr->next;
 
   /* could not find it */
-  if (!ptr || IS_SPEC (ptr) ||
-      DCL_TYPE (ptr) != UPOINTER)
+  if (!ptr || IS_SPEC (ptr))
+    return;
+  
+  if (IS_PTR(ptr) && DCL_TYPE(ptr)!=UPOINTER) {
+    pointerTypes (ptr->next, type);
     return;
+  }
 
   /* change the pointer type depending on the
      storage class of the type */
@@ -412,7 +415,7 @@ addDecl (symbol * sym, int type, sym_link * p)
     {
       if (IS_SPEC (sym->etype) && IS_SPEC (head) && head == tail)
        {
-         sym->etype = mergeSpec (sym->etype, head);
+         sym->etype = mergeSpec (sym->etype, head, sym->name);
        }
       else
        {
@@ -432,13 +435,13 @@ addDecl (symbol * sym, int type, sym_link * p)
        }
     }
 
-  /* if the type is a unknown pointer and has
+  /* if the type is an unknown pointer and has
      a tspec then take the storage class const & volatile
      attribute from the tspec & make it those of this
      symbol */
   if (p &&
       !IS_SPEC (p) &&
-      DCL_TYPE (p) == UPOINTER &&
+      //DCL_TYPE (p) == UPOINTER &&
       DCL_TSPEC (p))
     {
       if (!IS_SPEC (sym->etype))
@@ -478,47 +481,43 @@ void checkTypeSanity(sym_link *etype, char *name) {
   noun=nounName(etype);
 
   if (getenv("DEBUG_SANITY")) {
-    fprintf (stderr, "checking sanity for %s\n", name);
+    fprintf (stderr, "checking sanity for %s %x\n", name, (int)etype);
   }
 
   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))) {
+      (etype->select.s._short || 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))) {
+      (etype->select.s._signed || 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;
-    }
+  // special case for "short"
+  if (etype->select.s._short) {
+    SPEC_NOUN(etype) = options.shortis8bits ? V_CHAR : V_INT;
+    etype->select.s._short = 0;
   }
 
-  // if still no noun (e.g. "const a;" or "data b;") assume an int
+  /* if no noun e.g. 
+     "const a;" or "data b;" or "signed s" or "long l"
+     assume an int */
   if (!SPEC_NOUN(etype)) {
     SPEC_NOUN(etype)=V_INT;
   }
 
-  if (SPEC_SIGNED(etype) && SPEC_USIGN(etype)) {
+  if (etype->select.s._signed && SPEC_USIGN(etype)) {
     // signed AND unsigned 
     werror (E_SIGNED_AND_UNSIGNED_INVALID, noun, name);
   }
-  if (SPEC_SHORT(etype) && SPEC_LONG(etype)) {
+  if (etype->select.s._short && SPEC_LONG(etype)) {
     // short AND long
     werror (E_LONG_AND_SHORT_INVALID, noun, name);
   }
@@ -529,9 +528,38 @@ void checkTypeSanity(sym_link *etype, char *name) {
 /* mergeSpec - merges two specifiers and returns the new one        */
 /*------------------------------------------------------------------*/
 sym_link *
-mergeSpec (sym_link * dest, sym_link * src)
+mergeSpec (sym_link * dest, sym_link * src, char *name)
 {
 
+  sym_link *symlink;
+
+  if (!IS_SPEC(dest)) {
+    // This can happen for pointers, find the end type
+    while (dest && !IS_SPEC(dest))
+      dest=dest->next;
+  }
+  if (!IS_SPEC(src)) {
+    // here we have a declarator as source, reverse them
+    symlink=src;
+    src=dest;
+    dest=symlink;
+    while (dest && !IS_SPEC(dest)) {
+      // and find the specifier
+      dest=dest->next;
+    }
+  } else {
+    symlink=dest;
+  }
+
+  if (!IS_SPEC(dest) || !IS_SPEC(src)) {
+    werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "cannot merge declarator");
+    exit (1);
+  }
+
+  if (getenv("DEBUG_mergeSpec")) {
+    fprintf (stderr, "mergeSpec: \"%s\"\n", name);
+  }
+
   if (SPEC_NOUN(src)) {
     if (!SPEC_NOUN(dest)) {
       SPEC_NOUN(dest)=SPEC_NOUN(src);
@@ -539,8 +567,8 @@ mergeSpec (sym_link * dest, sym_link * src)
       /* we shouldn't redeclare the type */
       if (getenv("DEBUG_SANITY")) {
        fprintf (stderr, "mergeSpec: ");
-       werror(E_TWO_OR_MORE_DATA_TYPES, yylval.yychar);
       }
+      werror(E_TWO_OR_MORE_DATA_TYPES, name);
     }
   }
   
@@ -552,7 +580,7 @@ mergeSpec (sym_link * dest, sym_link * src)
       if (getenv("DEBUG_SANITY")) {
        fprintf (stderr, "mergeSpec: ");
       }
-      werror(E_TWO_OR_MORE_STORAGE_CLASSES, yylval.yychar);
+      werror(E_TWO_OR_MORE_STORAGE_CLASSES, name);
     }
   }
 
@@ -564,15 +592,15 @@ mergeSpec (sym_link * dest, sym_link * src)
     if (SPEC_what(dest)) {
       werror(W_DUPLICATE_SPEC, "what");
     }
-    SPEC_what(dst)=SPEC_what(src);
+    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);
+  dest->select.s._short|=src->select.s._short;
   SPEC_USIGN (dest) |= SPEC_USIGN (src);
-  SPEC_SIGNED (dest) |= SPEC_SIGNED (src);
+  dest->select.s._signed|=src->select.s._signed;
   SPEC_STAT (dest) |= SPEC_STAT (src);
   SPEC_EXTR (dest) |= SPEC_EXTR (src);
   SPEC_ABSA (dest) |= SPEC_ABSA (src);
@@ -592,7 +620,7 @@ mergeSpec (sym_link * dest, sym_link * src)
   if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
     SPEC_STRUCT (dest) = SPEC_STRUCT (src);
 
-  return dest;
+  return symlink;
 }
 
 /*------------------------------------------------------------------*/
@@ -715,7 +743,7 @@ getSize (sym_link * p)
       switch (SPEC_NOUN (p))
        {                       /* depending on the specifier type */
        case V_INT:
-         return (IS_LONG (p) ? LONGSIZE : (IS_SHORT (p) ? SHORTSIZE : INTSIZE));
+         return (IS_LONG (p) ? LONGSIZE : INTSIZE);
        case V_FLOAT:
          return FLOATSIZE;
        case V_CHAR:
@@ -774,7 +802,7 @@ bitsForType (sym_link * p)
       switch (SPEC_NOUN (p))
        {                       /* depending on the specifier type */
        case V_INT:
-         return (IS_LONG (p) ? LONGSIZE * 8 : (IS_SHORT (p) ? SHORTSIZE * 8 : INTSIZE * 8));
+         return (IS_LONG (p) ? LONGSIZE * 8 : INTSIZE * 8);
        case V_FLOAT:
          return FLOATSIZE * 8;
        case V_CHAR:
@@ -918,49 +946,37 @@ addSymChain (symbol * symHead)
   symbol *sym = symHead;
   symbol *csym = NULL;
 
-
   for (; sym != NULL; sym = sym->next)
     {
       changePointer(sym);
+      checkTypeSanity(sym->etype, sym->name);
 
       /* if already exists in the symbol table then check if
-         the previous was an extern definition if yes then
+         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)
-       {
-
-         /* previous definition extern ? */
-         if (IS_EXTERN (csym->etype))
-           {
-             /* do types match ? */
-             if (checkType (csym->type, sym->type) != 1)
-               /* no then error */
-               werror (E_DUPLICATE, csym->name);
-
-             /* delete current entry */
-             deleteSym (SymbolTab, csym, csym->name);
-             /* add new entry */
-             addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
-           }
-         else                  /* not extern */
-           werror (E_DUPLICATE, sym->name);
+         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;
+         }
+         /* delete current entry */
+         deleteSym (SymbolTab, csym, csym->name);
+       } else {
+         /* not extern */
+         werror (E_DUPLICATE, sym->name);
          continue;
        }
+      }
 
-      /* check if previously defined */
-      if (csym && csym->level == sym->level)
-       {
-         /* if the previous one was declared as extern */
-         /* then check the type with the current one         */
-         if (IS_EXTERN (csym->etype))
-           {
-             if (checkType (csym->type, sym->type) <= 0)
-               werror (W_EXTERN_MISMATCH, csym->name);
-           }
-       }
-      addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+      /* add new entry */
+      addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
     }
 }
 
@@ -1078,7 +1094,7 @@ compStructSize (int su, structdef * sdef)
            }
        }
        else {
-           checkDecl (loop);
+           checkDecl (loop, 1);
            sum += getSize (loop->type);
        }
 
@@ -1110,13 +1126,20 @@ compStructSize (int su, structdef * sdef)
 /* checkSClass - check the storage class specification              */
 /*------------------------------------------------------------------*/
 static void 
-checkSClass (symbol * sym)
+checkSClass (symbol * sym, int isProto)
 {
+  if (getenv("DEBUG_SANITY")) {
+    fprintf (stderr, "checkSClass: %s \n", sym->name);
+  }
+  if (strcmp(sym->name, "_testsGlobal")==0) {
+    printf ("oach\n");
+  }
+  
   /* type is literal can happen foe enums change
      to auto */
   if (SPEC_SCLS (sym->etype) == S_LITERAL && !SPEC_ENUM (sym->etype))
     SPEC_SCLS (sym->etype) = S_AUTO;
-
+  
   /* if sfr or sbit then must also be */
   /* volatile the initial value will be xlated */
   /* to an absolute address */
@@ -1133,26 +1156,24 @@ checkSClass (symbol * sym)
          sym->ival = NULL;
        }
     }
-
+  
   /* if absolute address given then it mark it as
      volatile */
   if (IS_ABSOLUTE (sym->etype))
     SPEC_VOLATILE (sym->etype) = 1;
-
+  
   /* global variables declared const put into code */
   if (sym->level == 0 &&
-      SPEC_SCLS (sym->etype) == S_CONSTANT)
-    {
-      SPEC_SCLS (sym->etype) = S_CODE;
-      SPEC_CONST (sym->etype) = 1;
-    }
-
+      SPEC_CONST (sym->etype)) {
+    SPEC_SCLS (sym->etype) = S_CODE;
+  }
+  
   /* global variable in code space is a constant */
   if (sym->level == 0 &&
       SPEC_SCLS (sym->etype) == S_CODE &&
       port->mem.code_ro)
     SPEC_CONST (sym->etype) = 1;
-
+  
 
   /* if bit variable then no storage class can be */
   /* specified since bit is already a storage */
@@ -1173,23 +1194,22 @@ checkSClass (symbol * sym)
       sym->ival = NULL;
     }
 
-  /* if this is an automatic symbol then */
-  /* storage class will be ignored and   */
-  /* symbol will be allocated on stack/  */
-  /* data depending on flag             */
-  if (sym->level &&
-      (options.stackAuto || reentrant) &&
-      (SPEC_SCLS (sym->etype) != S_AUTO &&
-       SPEC_SCLS (sym->etype) != S_FIXED &&
-       SPEC_SCLS (sym->etype) != S_REGISTER &&
-       SPEC_SCLS (sym->etype) != S_STACK &&
-       SPEC_SCLS (sym->etype) != S_XSTACK &&
-       SPEC_SCLS (sym->etype) != S_CONSTANT))
-    {
-      werror (E_AUTO_ASSUMED, sym->name);
+  /* if this is an atomatic symbol */
+  if (sym->level && (options.stackAuto || reentrant)) {
+    if ((SPEC_SCLS (sym->etype) == S_AUTO ||
+        SPEC_SCLS (sym->etype) == S_FIXED ||
+        SPEC_SCLS (sym->etype) == S_REGISTER ||
+        SPEC_SCLS (sym->etype) == S_STACK ||
+        SPEC_SCLS (sym->etype) == S_XSTACK)) {
       SPEC_SCLS (sym->etype) = S_AUTO;
+    } else {
+      /* storage class may only be specified for statics */
+      if (!IS_STATIC(sym->etype)) {
+       werror (E_AUTO_ASSUMED, sym->name);
+      }
     }
-
+  }
+  
   /* automatic symbols cannot be given   */
   /* an absolute address ignore it      */
   if (sym->level &&
@@ -1216,15 +1236,17 @@ checkSClass (symbol * sym)
       SPEC_BSTR (sym->etype) = 0;
     }
 
-  /* variables declared in CODE space must have */
-  /* initializers if not an extern */
-  if (SPEC_SCLS (sym->etype) == S_CODE &&
-      sym->ival == NULL &&
-      !sym->level &&
-      port->mem.code_ro &&
-      !IS_EXTERN (sym->etype) &&
-      !funcInChain (sym->type))
-    werror (E_CODE_NO_INIT, sym->name);
+  if (!isProto) {
+    /* variables declared in CODE space must have */
+    /* initializers if not an extern */
+    if (SPEC_SCLS (sym->etype) == S_CODE &&
+       sym->ival == NULL &&
+       //!sym->level &&
+       port->mem.code_ro &&
+       !IS_EXTERN (sym->etype) &&
+       !funcInChain (sym->type))
+      werror (E_CODE_NO_INIT, sym->name);
+  }
 
   /* if parameter or local variable then change */
   /* the storage class to reflect where the var will go */
@@ -1274,10 +1296,10 @@ changePointer (symbol * sym)
 /* checkDecl - does semantic validation of a declaration                   */
 /*------------------------------------------------------------------*/
 int 
-checkDecl (symbol * sym)
+checkDecl (symbol * sym, int isProto)
 {
 
-  checkSClass (sym);           /* check the storage class      */
+  checkSClass (sym, isProto);          /* check the storage class      */
   changePointer (sym);         /* change pointers if required */
 
   /* if this is an array without any dimension
@@ -1405,11 +1427,11 @@ computeType (sym_link * type1, sym_link * type2)
   return rType;
 }
 
-/*------------------------------------------------------------------*/
-/* checkType - will do type check return 1 if match                 */
-/*------------------------------------------------------------------*/
+/*--------------------------------------------------------------------*/
+/* compareType - will do type check return 1 if match, -1 if castable */
+/*--------------------------------------------------------------------*/
 int 
-checkType (sym_link * dest, sym_link * src)
+compareType (sym_link * dest, sym_link * src)
 {
   if (!dest && !src)
     return 1;
@@ -1426,15 +1448,14 @@ checkType (sym_link * dest, sym_link * src)
       if (IS_DECL (src))
        {
          if (DCL_TYPE (src) == DCL_TYPE (dest))
-           return checkType (dest->next, src->next);
-         else if (IS_PTR (src) && IS_PTR (dest))
+           return compareType (dest->next, src->next);
+         if (IS_PTR (src) && IS_PTR (dest))
            return -1;
-         else if (IS_PTR (dest) && IS_ARRAY (src))
+         if (IS_PTR (dest) && IS_ARRAY (src))
            return -1;
-         else if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src))
-           return -1 * checkType (dest->next, src);
-         else
-           return 0;
+         if (IS_PTR (dest) && IS_FUNC (dest->next) && IS_FUNC (src))
+           return -1 * compareType (dest->next, src);
+         return 0;
        }
       else if (IS_PTR (dest) && IS_INTEGRAL (src))
        return -1;
@@ -1456,17 +1477,6 @@ checkType (sym_link * dest, sym_link * src)
       SPEC_NOUN (src) == V_VOID)
     return -1;
 
-  /* char === to short */
-  if (SPEC_NOUN (dest) == V_CHAR &&
-      SPEC_NOUN (src) == V_INT &&
-      SPEC_SHORT (src))
-    return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2);
-
-  if (SPEC_NOUN (src) == V_CHAR &&
-      SPEC_NOUN (dest) == V_INT &&
-      SPEC_SHORT (dest))
-    return (SPEC_USIGN (src) == SPEC_USIGN (dest) ? 1 : -2);
-
   /* if they are both bitfields then if the lengths
      and starts don't match */
   if (IS_BITFIELD (dest) && IS_BITFIELD (src) &&
@@ -1496,17 +1506,14 @@ checkType (sym_link * dest, sym_link * src)
   if (SPEC_LONG (dest) != SPEC_LONG (src))
     return -1;
 
-  if (SPEC_SHORT (dest) != SPEC_SHORT (src))
-    return -1;
-
   if (SPEC_USIGN (dest) != SPEC_USIGN (src))
-    return -2;
+    return -1;
 
   return 1;
 }
 
 /*------------------------------------------------------------------*/
-/* inCalleeSaveList - return 1 if found in calle save list          */
+/* inCalleeSaveList - return 1 if found in callee save list          */
 /*------------------------------------------------------------------*/
 bool 
 inCalleeSaveList (char *s)
@@ -1597,6 +1604,7 @@ checkFunction (symbol * sym)
 {
   symbol *csym;
   value *exargs, *acargs;
+  value *checkValue;
   int argCnt = 0;
 
   if (getenv("DEBUG_SANITY")) {
@@ -1651,13 +1659,13 @@ checkFunction (symbol * sym)
     }
 
   /* check the return value type   */
-  if (checkType (csym->type, sym->type) <= 0)
+  if (compareType (csym->type, sym->type) <= 0)
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "type");
-      werror (E_CONTINUE, "previous definition type ");
+      werror (W_CONTINUE, "previous definition type ");
       printTypeChain (csym->type, stderr);
       fprintf (stderr, "\n");
-      werror (E_CONTINUE, "current definition type ");
+      werror (W_CONTINUE, "current definition type ");
       printTypeChain (sym->type, stderr);
       fprintf (stderr, "\n");
       return 0;
@@ -1666,13 +1674,16 @@ checkFunction (symbol * sym)
   if (SPEC_INTRTN (csym->etype) != SPEC_INTRTN (sym->etype))
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt");
-      return 0;
     }
 
   if (SPEC_BANK (csym->etype) != SPEC_BANK (sym->etype))
     {
       werror (E_PREV_DEF_CONFLICT, csym->name, "using");
-      return 0;
+    }
+
+  if (SPEC_NAKED (csym->etype) != SPEC_NAKED (sym->etype))
+    {
+      werror (E_PREV_DEF_CONFLICT, csym->name, "_naked");
     }
 
   /* compare expected agrs with actual args */
@@ -1684,7 +1695,12 @@ checkFunction (symbol * sym)
        exargs && acargs;
        exargs = exargs->next, acargs = acargs->next, argCnt++)
     {
-      value *checkValue;
+      if (getenv("DEBUG_SANITY")) {
+       fprintf (stderr, "checkFunction: %s ", exargs->name);
+      }
+      /* make sure the type is complete and sane */
+      checkTypeSanity(exargs->etype, exargs->name);
+
       /* If the actual argument is an array, any prototype
        * will have modified it to a pointer. Duplicate that
        * change here.
@@ -1699,7 +1715,7 @@ checkFunction (symbol * sym)
          checkValue = acargs;
        }
 
-      if (checkType (exargs->type, checkValue->type) <= 0)
+      if (compareType (exargs->type, checkValue->type) <= 0)
        {
          werror (E_ARG_TYPE, argCnt);
          return 0;
@@ -1714,7 +1730,7 @@ checkFunction (symbol * sym)
   /* replace with this defition */
   sym->cdef = csym->cdef;
   deleteSym (SymbolTab, csym, csym->name);
-  addSym (SymbolTab, sym, sym->name, sym->level, sym->block);
+  addSym (SymbolTab, sym, sym->name, sym->level, sym->block, 1);
   if (IS_EXTERN (csym->etype) && !
       IS_EXTERN (sym->etype))
     {
@@ -1936,8 +1952,6 @@ printTypeChain (sym_link * type, FILE * of)
            case V_INT:
              if (IS_LONG (type))
                fprintf (of, "long ");
-             if (IS_SHORT (type))
-               fprintf (of, "short ");
              fprintf (of, "int ");
              break;
 
@@ -2031,8 +2045,6 @@ cdbTypeInfo (sym_link * type, FILE * of)
            case V_INT:
              if (IS_LONG (type))
                fprintf (of, "SL");
-             else if (IS_SHORT (type))
-               fprintf (of, "SS");
              else
                fprintf (of, "SI");
              break;
@@ -2222,22 +2234,21 @@ symbol *__muldiv[3][3][2];
 sym_link *__multypes[3][2];
 /* Dims: to/from float, BYTE/WORD/DWORD, SIGNED/USIGNED */
 symbol *__conv[2][3][2];
+/* Dims: shift left/shift right, BYTE/WORD/DWORD, SIGNED/UNSIGNED */
+symbol *__rlrr[2][3][2];
 
 sym_link *floatType;
 
-static void 
-_makeRegParam (symbol * sym)
+static char *
+_mangleFunctionName(char *in)
 {
-  value *val;
-
-  val = sym->args;             /* loop thru all the arguments   */
-
-  /* reset regparm for the port */
-  (*port->reset_regparms) ();
-  while (val)
+  if (port->getMangledFunctionName) 
     {
-      SPEC_REGPARM (val->etype) = 1;
-      val = val->next;
+      return port->getMangledFunctionName(in);
+    }
+  else
+    {
+      return in;
     }
 }
 
@@ -2259,8 +2270,17 @@ initCSupport ()
   {
     "s", "u"
   };
+  const char *srlrr[] =
+  {
+    "rl", "rr"
+  };
+
+  int bwd, su, muldivmod, tofrom, rlrr;
 
-  int bwd, su, muldivmod, tofrom;
+  if (getenv("SDCC_NO_C_SUPPORT")) {
+    /* for debugging only */
+    return;
+  }
 
   floatType = newFloatLink ();
 
@@ -2306,12 +2326,12 @@ initCSupport ()
              if (tofrom)
                {
                  sprintf (buffer, "__fs2%s%s", ssu[su], sbwd[bwd]);
-                 __conv[tofrom][bwd][su] = funcOfType (buffer, __multypes[bwd][su], floatType, 1, options.float_rent);
+                 __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], floatType, 1, options.float_rent);
                }
              else
                {
                  sprintf (buffer, "__%s%s2fs", ssu[su], sbwd[bwd]);
-                 __conv[tofrom][bwd][su] = funcOfType (buffer, floatType, __multypes[bwd][su], 1, options.float_rent);
+                 __conv[tofrom][bwd][su] = funcOfType (_mangleFunctionName(buffer), floatType, __multypes[bwd][su], 1, options.float_rent);
                }
            }
        }
@@ -2327,10 +2347,24 @@ 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 (_mangleFunctionName(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]);
+           }
+       }
+    }
+
+  for (rlrr = 0; rlrr < 2; rlrr++)
+    {
+      for (bwd = 0; bwd < 3; bwd++)
+       {
+         for (su = 0; su < 2; su++)
+           {
+             sprintf (buffer, "_%s%s%s",
+                      srlrr[rlrr],
+                      ssu[su],
+                      sbwd[bwd]);
+              __rlrr[rlrr][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[0][0], 2, options.intlong_rent);
+             SPEC_NONBANKED (__rlrr[rlrr][bwd][su]->etype) = 1;
            }
        }
     }