]> git.sur5r.net Git - cc65/commitdiff
Moved the fascall and near/far flags from the function desriptor into the
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 24 Aug 2008 17:33:30 +0000 (17:33 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 24 Aug 2008 17:33:30 +0000 (17:33 +0000)
type. Started to add general handling of address size flags in types.

git-svn-id: svn://svn.cc65.org/cc65/trunk@3891 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codeinfo.c
src/cc65/codeseg.c
src/cc65/datatype.c
src/cc65/datatype.h
src/cc65/declare.c
src/cc65/expr.c
src/cc65/funcdesc.h
src/cc65/function.c
src/cc65/typecmp.c
src/cc65/typeconv.c

index fb6bea66702922544b8b4607099eeba86e2f0e55..1eec549644957d3f17cf5c216311b24f0cbc72aa 100644 (file)
@@ -340,14 +340,15 @@ void GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
        /* Did we find it in the top level table? */
        if (E && IsTypeFunc (E->Type)) {
 
+            FuncDesc* D = E->V.F.Func;
+
            /* A function may use the A or A/X registers if it is a fastcall
             * function. If it is not a fastcall function but a variadic one,
             * it will use the Y register (the parameter size is passed here).
             * In all other cases, no registers are used. However, we assume
             * that any function will destroy all registers.
             */
-           FuncDesc* D = E->V.F.Func;
-           if ((D->Flags & FD_FASTCALL) != 0 && D->ParamCount > 0) {
+           if (IsQualFastcall (E->Type) && D->ParamCount > 0) {
                /* Will use registers depending on the last param */
                 unsigned LastParamSize = CheckedSizeOf (D->LastParam->Type);
                if (LastParamSize == 1) {
index 0b90a73fc36e7646fb4b57a3f2281c237a765b18..ad1b3aeb7c47a087d22f3d0972b94dc059549c14 100644 (file)
@@ -1241,12 +1241,11 @@ void CS_OutputPrologue (const CodeSeg* S, FILE* F)
      */
     if (Func) {
         /* Get the function descriptor */
-        const FuncDesc* D = GetFuncDesc (Func->Type);
                CS_PrintFunctionHeader (S, F);
         fprintf (F, ".segment\t\"%s\"\n\n.proc\t_%s", S->SegName, Func->Name);
-        if (D->Flags & FD_NEAR) {
+        if (IsQualNear (Func->Type)) {
             fputs (": near", F);
-        } else if (D->Flags & FD_FAR) {
+        } else if (IsQualFar (Func->Type)) {
             fputs (": far", F);
         }
         fputs ("\n\n", F);
index 738a8afaac81951c10de2e0c384d5237b5e76e4b..fc71d3df2a1176768effb8c09be61c5d65c10566 100644 (file)
@@ -36,7 +36,9 @@
 #include <string.h>
 
 /* common */
+#include "addrsize.h"
 #include "check.h"
+#include "mmodel.h"
 #include "xmalloc.h"
 
 /* cc65 */
@@ -208,7 +210,7 @@ Type* PointerTo (const Type* T)
     Type* P = TypeAlloc        (Size + 1);
 
     /* Create the return type... */
-    P[0].C = T_PTR;
+    P[0].C = T_PTR | (T[0].C & T_QUAL_ADDRSIZE);
     memcpy (P+1, T, Size * sizeof (Type));
 
     /* ...and return it */
@@ -240,69 +242,72 @@ void PrintType (FILE* F, const Type* T)
         /* Get the type code */
         TypeCode C = T->C;
 
-       /* Print any qualifiers */
+       /* Print any qualifiers */
                C = PrintTypeComp (F, C, T_QUAL_CONST, "const");
-       C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile");
+       C = PrintTypeComp (F, C, T_QUAL_VOLATILE, "volatile");
         C = PrintTypeComp (F, C, T_QUAL_RESTRICT, "restrict");
+        C = PrintTypeComp (F, C, T_QUAL_NEAR, "__near__");
+        C = PrintTypeComp (F, C, T_QUAL_FAR, "__far__");
+        C = PrintTypeComp (F, C, T_QUAL_FASTCALL, "__fastcall__");
 
-       /* Signedness. Omit the signedness specifier for long and int */
+       /* Signedness. Omit the signedness specifier for long and int */
                if ((C & T_MASK_TYPE) != T_TYPE_INT && (C & T_MASK_TYPE) != T_TYPE_LONG) {
-           C = PrintTypeComp (F, C, T_SIGN_SIGNED, "signed");
-       }
-       C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
+           C = PrintTypeComp (F, C, T_SIGN_SIGNED, "signed");
+       }
+       C = PrintTypeComp (F, C, T_SIGN_UNSIGNED, "unsigned");
 
-       /* Now check the real type */
+       /* Now check the real type */
        switch (C & T_MASK_TYPE) {
-           case T_TYPE_CHAR:
-               fprintf (F, "char");
-               break;
-           case T_TYPE_SHORT:
-               fprintf (F, "short");
-               break;
-           case T_TYPE_INT:
-               fprintf (F, "int");
-               break;
-           case T_TYPE_LONG:
-               fprintf (F, "long");
-               break;
-           case T_TYPE_LONGLONG:
-               fprintf (F, "long long");
-               break;
-           case T_TYPE_FLOAT:
-               fprintf (F, "float");
-               break;
-           case T_TYPE_DOUBLE:
-               fprintf (F, "double");
-               break;
+           case T_TYPE_CHAR:
+               fprintf (F, "char");
+               break;
+           case T_TYPE_SHORT:
+               fprintf (F, "short");
+               break;
+           case T_TYPE_INT:
+               fprintf (F, "int");
+               break;
+           case T_TYPE_LONG:
+               fprintf (F, "long");
+               break;
+           case T_TYPE_LONGLONG:
+               fprintf (F, "long long");
+               break;
+           case T_TYPE_FLOAT:
+               fprintf (F, "float");
+               break;
+           case T_TYPE_DOUBLE:
+               fprintf (F, "double");
+               break;
            case T_TYPE_VOID:
                fprintf (F, "void");
-               break;
-           case T_TYPE_STRUCT:
-               fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
-               break;
-           case T_TYPE_UNION:
-               fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name);
-               break;
-           case T_TYPE_ARRAY:
-               /* Recursive call */
-               PrintType (F, T + 1);
-               if (T->A.L == UNSPECIFIED) {
-                   fprintf (F, "[]");
-               } else {
-                   fprintf (F, "[%ld]", T->A.L);
-               }
-               return;
-           case T_TYPE_PTR:
-               /* Recursive call */
-               PrintType (F, T + 1);
-               fprintf (F, "*");
-               return;
-           case T_TYPE_FUNC:
-               fprintf (F, "function returning ");
-               break;
-           default:
-               fprintf (F, "unknown type: %04lX", T->C);
-       }
+               break;
+           case T_TYPE_STRUCT:
+               fprintf (F, "struct %s", ((SymEntry*) T->A.P)->Name);
+               break;
+           case T_TYPE_UNION:
+               fprintf (F, "union %s", ((SymEntry*) T->A.P)->Name);
+               break;
+           case T_TYPE_ARRAY:
+               /* Recursive call */
+               PrintType (F, T + 1);
+               if (T->A.L == UNSPECIFIED) {
+                   fprintf (F, "[]");
+               } else {
+                   fprintf (F, "[%ld]", T->A.L);
+               }
+               return;
+           case T_TYPE_PTR:
+               /* Recursive call */
+               PrintType (F, T + 1);
+               fprintf (F, "*");
+               return;
+           case T_TYPE_FUNC:
+               fprintf (F, "function returning ");
+               break;
+           default:
+               fprintf (F, "unknown type: %04lX", T->C);
+       }
 
         /* Next element */
         ++T;
@@ -319,33 +324,33 @@ void PrintFuncSig (FILE* F, const char* Name, Type* T)
 
     /* Print a comment with the function signature */
     PrintType (F, GetFuncReturn (T));
-    if (D->Flags & FD_NEAR) {
+    if (IsQualNear (T)) {
         fprintf (F, " __near__");
     }
-    if (D->Flags & FD_FAR) {
+    if (IsQualFar (T)) {
         fprintf (F, " __far__");
     }
-    if (D->Flags & FD_FASTCALL) {
+    if (IsQualFastcall (T)) {
        fprintf (F, " __fastcall__");
     }
     fprintf (F, " %s (", Name);
 
     /* Parameters */
     if (D->Flags & FD_VOID_PARAM) {
-       fprintf (F, "void");
+       fprintf (F, "void");
     } else {
-       unsigned I;
-       SymEntry* E = D->SymTab->SymHead;
-       for (I = 0; I < D->ParamCount; ++I) {
-           if (I > 0) {
-               fprintf (F, ", ");
-           }
+       unsigned I;
+       SymEntry* E = D->SymTab->SymHead;
+       for (I = 0; I < D->ParamCount; ++I) {
+           if (I > 0) {
+               fprintf (F, ", ");
+           }
             if (SymIsRegVar (E)) {
                 fprintf (F, "register ");
             }
-           PrintType (F, E->Type);
-           E = E->NextSym;
-       }
+           PrintType (F, E->Type);
+           E = E->NextSym;
+       }
     }
 
     /* End of parameter list */
@@ -555,31 +560,6 @@ Type* ArrayToPtr (const Type* T)
 
 
 
-TypeCode GetQualifier (const Type* T)
-/* Get the qualifier from the given type string */
-{
-    /* If this is an array, look at the element type, otherwise look at the
-     * type itself.
-     */
-    if (IsTypeArray (T)) {
-       ++T;
-    }
-    return (T->C & T_MASK_QUAL);
-}
-
-
-
-int IsFastCallFunc (const Type* T)
-/* Return true if this is a function type or pointer to function with
- * __fastcall__ calling conventions
- */
-{
-    FuncDesc* F        = GetFuncDesc (T);
-    return (F->Flags & FD_FASTCALL) != 0;
-}
-
-
-
 int IsVariadicFunc (const Type* T)
 /* Return true if this is a function type or pointer to function type with
  * variable parameter list
@@ -723,10 +703,8 @@ Type* PtrConversion (Type* T)
  * return T.
  */
 {
-    if (IsTypeFunc (T)) {
+    if (IsTypeFunc (T) || IsTypeArray (T)) {
                return PointerTo (T);
-    } else if (IsTypeArray (T)) {
-        return ArrayToPtr (T);
     } else {
         return T;
     }
@@ -734,4 +712,27 @@ Type* PtrConversion (Type* T)
 
 
 
+TypeCode CodeAddrSizeQualifier (void)
+/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */
+{
+    if (CodeAddrSize == ADDR_SIZE_FAR) {
+        return T_QUAL_FAR;
+    } else {
+        return T_QUAL_NEAR;
+    }
+}
+
+
+
+TypeCode DataAddrSizeQualifier (void)
+/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */
+{
+    if (DataAddrSize == ADDR_SIZE_FAR) {
+        return T_QUAL_FAR;
+    } else {
+        return T_QUAL_NEAR;
+    }
+}
+
+
 
index 3b5b99245d12896d5aa5b26906b7deb9885f07df..84155f3050cdcf8b82655b6ce260442434afbde7 100644 (file)
 
 /* Basic data types */
 enum {
-    T_END          = 0x0000,
+    T_END                  = 0x000000,
 
     /* Basic types */
-    T_TYPE_NONE            = 0x0000,
-    T_TYPE_CHAR            = 0x0001,
-    T_TYPE_SHORT    = 0x0002,
-    T_TYPE_INT             = 0x0003,
-    T_TYPE_LONG            = 0x0004,
-    T_TYPE_LONGLONG = 0x0005,
-    T_TYPE_ENUM            = 0x0006,
-    T_TYPE_FLOAT    = 0x0007,
-    T_TYPE_DOUBLE   = 0x0008,
-    T_TYPE_VOID     = 0x0009,
-    T_TYPE_STRUCT   = 0x000A,
-    T_TYPE_UNION    = 0x000B,
-    T_TYPE_ARRAY    = 0x000C,
-    T_TYPE_PTR      = 0x000D,
-    T_TYPE_FUNC     = 0x000E,
-    T_MASK_TYPE            = 0x001F,
+    T_TYPE_NONE            = 0x000000,
+    T_TYPE_CHAR            = 0x000001,
+    T_TYPE_SHORT    = 0x000002,
+    T_TYPE_INT             = 0x000003,
+    T_TYPE_LONG            = 0x000004,
+    T_TYPE_LONGLONG = 0x000005,
+    T_TYPE_ENUM            = 0x000006,
+    T_TYPE_FLOAT    = 0x000007,
+    T_TYPE_DOUBLE   = 0x000008,
+    T_TYPE_VOID     = 0x000009,
+    T_TYPE_STRUCT   = 0x00000A,
+    T_TYPE_UNION    = 0x00000B,
+    T_TYPE_ARRAY    = 0x00000C,
+    T_TYPE_PTR      = 0x00000D,
+    T_TYPE_FUNC     = 0x00000E,
+    T_MASK_TYPE            = 0x00000F,
 
     /* Type classes */
-    T_CLASS_NONE    = 0x0000,
-    T_CLASS_INT            = 0x0020,
-    T_CLASS_FLOAT   = 0x0040,
-    T_CLASS_PTR            = 0x0060,
-    T_CLASS_STRUCT  = 0x0080,
-    T_CLASS_FUNC    = 0x00A0,
-    T_MASK_CLASS    = 0x00E0,
+    T_CLASS_NONE    = 0x000000,
+    T_CLASS_INT            = 0x000010,
+    T_CLASS_FLOAT   = 0x000020,
+    T_CLASS_PTR            = 0x000030,
+    T_CLASS_STRUCT  = 0x000040,
+    T_CLASS_FUNC    = 0x000050,
+    T_MASK_CLASS    = 0x000070,
 
     /* Type signedness */
-    T_SIGN_NONE            = 0x0000,
-    T_SIGN_UNSIGNED = 0x0100,
-    T_SIGN_SIGNED   = 0x0200,
-    T_MASK_SIGN     = 0x0300,
+    T_SIGN_NONE            = 0x000000,
+    T_SIGN_UNSIGNED = 0x000080,
+    T_SIGN_SIGNED   = 0x000100,
+    T_MASK_SIGN     = 0x000180,
 
     /* Type size modifiers */
-    T_SIZE_NONE            = 0x0000,
-    T_SIZE_SHORT    = 0x0400,
-    T_SIZE_LONG     = 0x0800,
-    T_SIZE_LONGLONG = 0x0C00,
-    T_MASK_SIZE            = 0x0C00,
+    T_SIZE_NONE            = 0x000000,
+    T_SIZE_SHORT    = 0x000200,
+    T_SIZE_LONG     = 0x000400,
+    T_SIZE_LONGLONG = 0x000600,
+    T_MASK_SIZE            = 0x000600,
 
     /* Type qualifiers */
-    T_QUAL_NONE     = 0x0000,
-    T_QUAL_CONST    = 0x1000,
-    T_QUAL_VOLATILE = 0x2000,
-    T_QUAL_RESTRICT = 0x4000,
-    T_MASK_QUAL            = 0x7000,
+    T_QUAL_NONE     = 0x000000,
+    T_QUAL_CONST    = 0x000800,
+    T_QUAL_VOLATILE = 0x001000,
+    T_QUAL_RESTRICT = 0x002000,
+    T_QUAL_NEAR     = 0x004000,
+    T_QUAL_FAR      = 0x008000,
+    T_QUAL_ADDRSIZE = T_QUAL_NEAR | T_QUAL_FAR,
+    T_QUAL_FASTCALL = 0x010000,
+    T_MASK_QUAL            = 0x01F800,
 
     /* Types */
     T_CHAR             = T_TYPE_CHAR     | T_CLASS_INT    | T_SIGN_UNSIGNED | T_SIZE_NONE,
@@ -506,43 +510,75 @@ INLINE int IsSignSigned (const Type* T)
 #  define IsSignSigned(T)       (GetSignedness (T) == T_SIGN_SIGNED)
 #endif
 
-TypeCode GetQualifier (const Type* T) attribute ((const));
+#if defined(HAVE_INLINE)
+INLINE TypeCode GetQualifier (const Type* T)
 /* Get the qualifier from the given type string */
+{
+    return (T->C & T_MASK_QUAL);
+}
+#else
+#  define GetQualifier(T)      ((T)->C & T_MASK_QUAL)
+#endif
 
 #if defined(HAVE_INLINE)
 INLINE int IsQualConst (const Type* T)
 /* Return true if the given type has a const memory image */
 {
-    return (GetQualifier (T) & T_QUAL_CONST) != 0;
+    return (T->C & T_QUAL_CONST) != 0;
 }
 #else
-#  define IsQualConst(T)        ((GetQualifier (T) & T_QUAL_CONST) != 0)
+#  define IsQualConst(T)        ((T->C & T_QUAL_CONST) != 0)
 #endif
 
 #if defined(HAVE_INLINE)
 INLINE int IsQualVolatile (const Type* T)
 /* Return true if the given type has a volatile type qualifier */
 {
-    return (GetQualifier (T) & T_QUAL_VOLATILE) != 0;
+    return (T->C & T_QUAL_VOLATILE) != 0;
 }
 #else
-#  define IsQualVolatile(T)     ((GetQualifier (T) & T_QUAL_VOLATILE) != 0)
+#  define IsQualVolatile(T)     (T->C & T_QUAL_VOLATILE) != 0)
 #endif
 
 #if defined(HAVE_INLINE)
 INLINE int IsQualRestrict (const Type* T)
 /* Return true if the given type has a restrict qualifier */
 {
-    return (GetQualifier (T) & T_QUAL_RESTRICT) != 0;
+    return (T->C & T_QUAL_RESTRICT) != 0;
 }
 #else
-#  define IsQualRestrict(T)     ((GetQualifier (T) & T_QUAL_RESTRICT) != 0)
+#  define IsQualRestrict(T)     (T->C & T_QUAL_RESTRICT) != 0)
 #endif
 
-int IsFastCallFunc (const Type* T) attribute ((const));
-/* Return true if this is a function type or pointer to function with
- * __fastcall__ calling conventions
- */
+#if defined(HAVE_INLINE)
+INLINE int IsQualNear (const Type* T)
+/* Return true if the given type has a near qualifier */
+{
+    return (T->C & T_QUAL_NEAR) != 0;
+}
+#else
+#  define IsQualNear(T)         (T->C & T_QUAL_NEAR) != 0)
+#endif
+
+#if defined(HAVE_INLINE)
+INLINE int IsQualFar (const Type* T)
+/* Return true if the given type has a far qualifier */
+{
+    return (T->C & T_QUAL_FAR) != 0;
+}
+#else
+#  define IsQualFar(T)          (T->C & T_QUAL_FAR) != 0)
+#endif
+
+#if defined(HAVE_INLINE)
+INLINE int IsQualFastcall (const Type* T)
+/* Return true if the given type has a fastcall qualifier */
+{
+    return (T->C & T_QUAL_FASTCALL) != 0;
+}
+#else
+#  define IsQualFastcall(T)     (T->C & T_QUAL_FASTCALL) != 0)
+#endif
 
 int IsVariadicFunc (const Type* T) attribute ((const));
 /* Return true if this is a function type or pointer to function type with
@@ -598,6 +634,12 @@ Type* PtrConversion (Type* T);
  * return T.
  */
 
+TypeCode CodeAddrSizeQualifier (void);
+/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the code address size */
+
+TypeCode DataAddrSizeQualifier (void);
+/* Return T_QUAL_NEAR or T_QUAL_FAR depending on the data address size */
+
 
 
 /* End of datatype.h */
index cf3521f8fcbdfcb4cbf0f42b138dc12f1951780f..640a04f69da1e3c2aecba0fb0b2ab2623aa6bfd5 100644 (file)
@@ -77,41 +77,94 @@ static unsigned ParseInitInternal (Type* T, int AllowFlexibleMembers);
 
 
 /*****************************************************************************/
-/*                           internal functions                             */
+/*                           internal functions                             */
 /*****************************************************************************/
 
 
 
-static TypeCode OptionalQualifiers (TypeCode Q)
+static void DuplicateQualifier (const char* Name)
+/* Print an error message */
+{
+    Warning ("Duplicate qualifier: `%s'", Name);
+}
+
+
+
+static TypeCode OptionalQualifiers (TypeCode Q, TypeCode Allowed)
 /* Read type qualifiers if we have any */
 {
-    while (TokIsTypeQual (&CurTok)) {
+    while (1) {
 
-       switch (CurTok.Tok) {
+       switch (CurTok.Tok) {
 
-           case TOK_CONST:
-               if (Q & T_QUAL_CONST) {
-                   Error ("Duplicate qualifier: `const'");
-               }
-               Q |= T_QUAL_CONST;
-               break;
+           case TOK_CONST:
+                if (Allowed & T_QUAL_CONST) {
+                    if (Q & T_QUAL_CONST) {
+                        DuplicateQualifier ("const");
+                    }
+                    Q |= T_QUAL_CONST;
+                } else {
+                    goto Done;
+                }
+                break;
 
            case TOK_VOLATILE:
-               if (Q & T_QUAL_VOLATILE) {
-                   Error ("Duplicate qualifier: `volatile'");
-               }
-               Q |= T_QUAL_VOLATILE;
-               break;
+                if (Allowed & T_QUAL_VOLATILE) {
+                    if (Q & T_QUAL_VOLATILE) {
+                        DuplicateQualifier ("volatile");
+                    }
+                    Q |= T_QUAL_VOLATILE;
+                } else {
+                    goto Done;
+                }
+               break;
 
             case TOK_RESTRICT:
-                if (Q & T_QUAL_RESTRICT) {
-                    Error ("Duplicate qualifier: `restrict'");
+                if (Allowed & T_QUAL_RESTRICT) {
+                    if (Q & T_QUAL_RESTRICT) {
+                        DuplicateQualifier ("restrict");
+                    }
+                    Q |= T_QUAL_RESTRICT;
+                } else {
+                    goto Done;
+                }
+                break;
+
+            case TOK_NEAR:
+                if (Allowed & T_QUAL_NEAR) {
+                    if (Q & T_QUAL_NEAR) {
+                        DuplicateQualifier ("near");
+                    }
+                    Q |= T_QUAL_NEAR;
+                } else {
+                    goto Done;
+                }
+                break;
+
+            case TOK_FAR:
+                if (Allowed & T_QUAL_FAR) {
+                    if (Q & T_QUAL_FAR) {
+                        DuplicateQualifier ("far");
+                    }
+                    Q |= T_QUAL_FAR;
+                } else {
+                    goto Done;
+                }
+                break;
+
+            case TOK_FASTCALL:
+                if (Allowed & T_QUAL_FASTCALL) {
+                    if (Q & T_QUAL_FASTCALL) {
+                        DuplicateQualifier ("fastcall");
+                    }
+                    Q |= T_QUAL_FASTCALL;
+                } else {
+                    goto Done;
                 }
-                Q |= T_QUAL_RESTRICT;
                 break;
 
            default:
-               Internal ("Unexpected type qualifier token: %d", CurTok.Tok);
+               goto Done;
 
        }
 
@@ -119,6 +172,7 @@ static TypeCode OptionalQualifiers (TypeCode Q)
        NextToken ();
     }
 
+Done:
     /* Return the qualifiers read */
     return Q;
 }
@@ -190,35 +244,18 @@ static void AddTypeToDeclaration (Declaration* D, TypeCode T)
 
 
 
-static void AddFuncTypeToDeclaration (Declaration* D, FuncDesc* F)
-/* Add a function type plus function descriptor to the type of a declaration */
+static void FixQualifiers (Type* DataType)
+/* Apply several fixes to qualifiers */
 {
-    NeedTypeSpace (D, 1);
-    D->Type[D->Index].C = T_FUNC;
-    SetFuncDesc (D->Type + D->Index, F);
-    ++D->Index;
-}
-
+    Type*    T;
+    TypeCode Q;
 
-
-static void AddArrayToDeclaration (Declaration* D, long Size)
-/* Add an array type plus size to the type of a declaration */
-{
-    NeedTypeSpace (D, 1);
-    D->Type[D->Index].C = T_ARRAY;
-    D->Type[D->Index].A.L = Size;
-    ++D->Index;
-}
-
-
-
-static void FixArrayQualifiers (Type* T)
-/* Using typedefs, it is possible to generate declarations that have
- * type qualifiers attached to an array, not the element type. Go and
- * fix these here.
- */
-{
-    TypeCode Q = T_QUAL_NONE;
+    /* Using typedefs, it is possible to generate declarations that have
+     * type qualifiers attached to an array, not the element type. Go and
+     * fix these here.
+     */
+    T = DataType;
+    Q = T_QUAL_NONE;
     while (T->C != T_END) {
         if (IsTypeArray (T)) {
             /* Extract any type qualifiers */
@@ -231,9 +268,69 @@ static void FixArrayQualifiers (Type* T)
         }
         ++T;
     }
-
     /* Q must be empty now */
     CHECK (Q == T_QUAL_NONE);
+
+    /* Do some fixes on pointers and functions. */
+    T = DataType;
+    while (T->C != T_END) {
+        if (IsTypePtr (T)) {
+
+            /* Fastcall qualifier on the pointer? */
+            if (IsQualFastcall (T)) {
+                /* Pointer to function which is not fastcall? */
+                if (IsTypeFunc (T+1) && !IsQualFastcall (T+1)) {
+                    /* Move the fastcall qualifier from the pointer to
+                     * the function.
+                     */
+                    T[0].C &= ~T_QUAL_FASTCALL;
+                    T[1].C |= T_QUAL_FASTCALL;
+                } else {
+                    Error ("Invalid `_fastcall__' qualifier for pointer");
+                }
+            }
+
+            /* Apply the default far and near qualifiers if none are given */
+            Q = (T[0].C & T_QUAL_ADDRSIZE);
+            if (Q == T_QUAL_NONE) {
+                /* No address size qualifiers specified */
+                if (IsTypeFunc (T+1)) {
+                    /* Pointer to function. Use the qualifier from the function
+                     * or the default if the function don't has one.
+                     */
+                    Q = (T[1].C & T_QUAL_ADDRSIZE);
+                    if (Q == T_QUAL_NONE) {
+                        Q = CodeAddrSizeQualifier ();
+                    }
+                } else {
+                    Q = DataAddrSizeQualifier ();
+                }
+                T[0].C |= Q;
+            } else {
+                /* We have address size qualifiers. If followed by a function,
+                 * apply these also to the function.
+                 */
+                if (IsTypeFunc (T+1)) {
+                    TypeCode FQ = (T[1].C & T_QUAL_ADDRSIZE);
+                    if (FQ == T_QUAL_NONE) {
+                        T[1].C |= Q;
+                    } else if (FQ != Q) {
+                        Error ("Address size qualifier mismatch");
+                        T[1].C = (T[1].C & ~T_QUAL_ADDRSIZE) | Q;
+                    }
+                }
+            }
+
+        } else if (IsTypeFunc (T)) {
+
+            /* Apply the default far and near qualifiers if none are given */
+            if ((T[0].C & T_QUAL_ADDRSIZE) == 0) {
+                T[0].C |= CodeAddrSizeQualifier ();
+            }
+
+        }
+        ++T;
+    }
 }
 
 
@@ -458,7 +555,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
     D->Flags &= ~DS_DEF_TYPE;
 
     /* Read type qualifiers if we have any */
-    Qualifiers = OptionalQualifiers (Qualifiers);
+    Qualifiers = OptionalQualifiers (Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE);
 
     /* Look at the data type */
     switch (CurTok.Tok) {
@@ -666,7 +763,7 @@ static void ParseTypeSpec (DeclSpec* D, long Default, TypeCode Qualifiers)
     }
 
     /* There may also be qualifiers *after* the initial type */
-    D->Type[0].C |= OptionalQualifiers (Qualifiers);
+    D->Type[0].C |= OptionalQualifiers (Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE);
 }
 
 
@@ -924,13 +1021,6 @@ static FuncDesc* ParseFuncDecl (void)
        Sym = Sym->PrevSym;
     }
 
-    /* Add the default address size for the function */
-    if (CodeAddrSize == ADDR_SIZE_FAR) {
-        F->Flags |= FD_FAR;
-    } else {
-        F->Flags |= FD_NEAR;
-    }
-
     /* Leave the lexical level remembering the symbol tables */
     RememberFunctionLevel (F);
 
@@ -940,111 +1030,48 @@ static FuncDesc* ParseFuncDecl (void)
 
 
 
-static unsigned FunctionModifierFlags (void)
-/* Parse __fastcall__, __near__ and __far__ and return the matching FD_ flags */
+static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
+/* Recursively process declarators. Build a type array in reverse order. */
 {
-    /* Read the flags */
-    unsigned Flags = FD_NONE;
-    while (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
-
-        /* Get the flag bit for the next token */
-        unsigned F = FD_NONE;
-        switch (CurTok.Tok) {
-            case TOK_FASTCALL:  F = FD_FASTCALL; break;
-            case TOK_NEAR:             F = FD_NEAR;     break;
-            case TOK_FAR:      F = FD_FAR;      break;
-            default:            Internal ("Unexpected token: %d", CurTok.Tok);
-        }
-
-        /* Remember the flag for this modifier */
-        if (Flags & F) {
-            Error ("Duplicate modifier");
-        }
-        Flags |= F;
-
-        /* Skip the token */
-        NextToken ();
-    }
-
-    /* Sanity check */
-    if ((Flags & (FD_NEAR | FD_FAR)) == (FD_NEAR | FD_FAR)) {
-        Error ("Cannot specify both, `__near__' and `__far__' modifiers");
-        Flags &= ~(FD_NEAR | FD_FAR);
-    }
-
-    /* Return the flags read */
-    return Flags;
-}
-
-
+    /* Read optional function or pointer qualifiers. These modify the
+     * identifier or token to the right. For convenience, we allow the fastcall
+     * qualifier also for pointers here. If it is a pointer-to-function, the
+     * qualifier will later be transfered to the function itself. If it's a
+     * pointer to something else, it will be flagged as an error.
+     */
+    TypeCode Qualifiers =
+        OptionalQualifiers (T_QUAL_NONE, T_QUAL_ADDRSIZE | T_QUAL_FASTCALL);
+
+    /* We cannot have more than one address size far qualifier */
+    switch (Qualifiers & T_QUAL_ADDRSIZE) {
+                  
+        case T_QUAL_NONE:
+        case T_QUAL_NEAR:
+        case T_QUAL_FAR:
+            break;
 
-static void ApplyFunctionModifiers (Type* T, unsigned Flags)
-/* Apply a set of function modifier flags to a function */
-{
-    /* Get the function descriptor */
-    FuncDesc* F = GetFuncDesc (T);
-
-    /* Special check for __fastcall__ */
-    if ((Flags & FD_FASTCALL) != 0 && IsVariadicFunc (T)) {
-        Error ("Cannot apply `__fastcall__' to functions with "
-               "variable parameter list");
-        Flags &= ~FD_FASTCALL;
+        default:
+            Error ("Cannot specify more than one address size qualifier");
+            Qualifiers &= ~T_QUAL_ADDRSIZE;
     }
 
-    /* Remove the default function address size modifiers */
-    F->Flags &= ~(FD_NEAR | FD_FAR);
-
-    /* Add the new modifers */
-    F->Flags |= Flags;
-}
-
-
-
-static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
-/* Recursively process declarators. Build a type array in reverse order. */
-{
     /* Pointer to something */
     if (CurTok.Tok == TOK_STAR) {
 
-       TypeCode C;
-
         /* Skip the star */
                NextToken ();
 
-       /* Allow optional const or volatile qualifiers */
-               C = T_PTR | OptionalQualifiers (T_QUAL_NONE);
+       /* Allow optional pointer qualifiers */
+        Qualifiers = OptionalQualifiers (Qualifiers, T_QUAL_CONST | T_QUAL_VOLATILE);
 
         /* Parse the type, the pointer points to */
                Decl (Spec, D, Mode);
 
        /* Add the type */
-       AddTypeToDeclaration (D, C);
+       AddTypeToDeclaration (D, T_PTR | Qualifiers);
                return;
     }
 
-    /* Function modifiers */
-    if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
-
-       /* Remember the current type pointer */
-       Type* T = D->Type + D->Index;
-
-       /* Read the flags */
-       unsigned Flags = FunctionModifierFlags ();
-
-       /* Parse the function */
-       Decl (Spec, D, Mode);
-
-       /* Check that we have a function */
-       if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
-           Error ("Function modifier applied to non function");
-       } else {
-            ApplyFunctionModifiers (T, Flags);
-        }
-
-       /* Done */
-       return;
-    }
-
     if (CurTok.Tok == TOK_LPAREN) {
                NextToken ();
                Decl (Spec, D, Mode);
@@ -1078,17 +1105,41 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
 
                    /* Function declaration */
            FuncDesc* F;
+
+            /* Skip the opening paren */
                    NextToken ();
 
            /* Parse the function declaration */
                    F = ParseFuncDecl ();
 
+            /* We cannot specify fastcall for variadic functions */
+            if ((F->Flags & FD_VARIADIC) && (Qualifiers & T_QUAL_FASTCALL)) {
+                Error ("Variadic functions cannot be `__fastcall'");
+                Qualifiers &= ~T_QUAL_FASTCALL;
+            }
+
            /* Add the function type. Be sure to bounds check the type buffer */
-           AddFuncTypeToDeclaration (D, F);
+            NeedTypeSpace (D, 1);
+            D->Type[D->Index].C = T_FUNC | Qualifiers;
+            D->Type[D->Index].A.P = F;
+            ++D->Index;
+
+            /* Qualifiers now used */
+            Qualifiers = T_QUAL_NONE;
+
                } else {
-           /* Array declaration */
+           /* Array declaration. */
                    long Size = UNSPECIFIED;
+
+            /* We cannot have any qualifiers for an array */
+            if (Qualifiers != T_QUAL_NONE) {
+                Error ("Invalid qualifiers for array");
+                Qualifiers = T_QUAL_NONE;
+            }
+
+            /* Skip the left bracket */
                    NextToken ();
+
            /* Read the size if it is given */
                    if (CurTok.Tok != TOK_RBRACK) {
                ExprDesc Expr;
@@ -1103,12 +1154,28 @@ static void Decl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
                 }
                        Size = Expr.IVal;
                    }
+
+            /* Skip the right bracket */
                    ConsumeRBrack ();
 
-           /* Add the array type with the size */
-           AddArrayToDeclaration (D, Size);
+           /* Add the array type with the size to the type */
+            NeedTypeSpace (D, 1);
+            D->Type[D->Index].C = T_ARRAY;
+            D->Type[D->Index].A.L = Size;
+            ++D->Index;
                }
     }
+
+    /* If we have remaining qualifiers, flag them as invalid */
+    if (Qualifiers & T_QUAL_NEAR) {
+        Error ("Invalid `__near__' qualifier");
+    }
+    if (Qualifiers & T_QUAL_FAR) {
+        Error ("Invalid `__far__' qualifier");
+    }
+    if (Qualifiers & T_QUAL_FASTCALL) {
+        Error ("Invalid `__fastcall__' qualifier");
+    }
 }
 
 
@@ -1157,8 +1224,8 @@ void ParseDecl (const DeclSpec* Spec, Declaration* D, unsigned Mode)
     /* Use the storage class from the declspec */
     D->StorageClass = Spec->StorageClass;
 
-    /* Fix any type qualifiers attached to an array type */
-    FixArrayQualifiers (D->Type);
+    /* Do several fixes on qualifiers */
+    FixQualifiers (D->Type);
 
     /* If we have a function, add a special storage class */
     if (IsTypeFunc (D->Type)) {
@@ -1243,7 +1310,7 @@ void ParseDeclSpec (DeclSpec* D, unsigned DefStorage, long DefType)
     InitDeclSpec (D);
 
     /* There may be qualifiers *before* the storage class specifier */
-    Qualifiers = OptionalQualifiers (T_QUAL_NONE);
+    Qualifiers = OptionalQualifiers (T_QUAL_NONE, T_QUAL_CONST | T_QUAL_VOLATILE);
 
     /* Now get the storage class specifier for this declaration */
     ParseStorageClass (D, DefStorage);
index 052e26423d4559ca27b887938ed8caa58fe2c1ff..6fb2d5e27358fcd50f20209601a0fb7caba389f8 100644 (file)
@@ -242,12 +242,12 @@ void PushAddr (const ExprDesc* Expr)
 
 
 /*****************************************************************************/
-/*                                  code                                    */
+/*                                  code                                    */
 /*****************************************************************************/
 
 
 
-static unsigned FunctionParamList (FuncDesc* Func)
+static unsigned FunctionParamList (FuncDesc* Func, int IsFastcall)
 /* Parse a function parameter list and pass the parameters to the called
  * function. Depending on several criteria this may be done by just pushing
  * each parameter separately, or creating the parameter frame once and then
@@ -284,7 +284,7 @@ static unsigned FunctionParamList (FuncDesc* Func)
        /* Calculate the number and size of the parameters */
        FrameParams = Func->ParamCount;
        FrameSize   = Func->ParamSize;
-       if (FrameParams > 0 && (Func->Flags & FD_FASTCALL) != 0) {
+       if (FrameParams > 0 && IsFastcall) {
            /* Last parameter is not pushed */
            FrameSize -= CheckedSizeOf (Func->LastParam->Type);
            --FrameParams;
@@ -371,7 +371,7 @@ static unsigned FunctionParamList (FuncDesc* Func)
                Flags |= TypeOf (Expr.Type);
 
        /* If this is a fastcall function, don't push the last argument */
-               if (ParamCount != Func->ParamCount || (Func->Flags & FD_FASTCALL) == 0) {
+               if (ParamCount != Func->ParamCount || !IsFastcall) {
            unsigned ArgSize = sizeofarg (Flags);
            if (FrameSize > 0) {
                /* We have the space already allocated, store in the frame.
@@ -430,7 +430,7 @@ static void FunctionCall (ExprDesc* Expr)
     unsigned     ParamSize;      /* Number of parameter bytes */
     CodeMark             Mark;
     int           PtrOffs = 0;    /* Offset of function pointer on stack */
-    int           IsFastCall = 0; /* True if it's a fast call function */
+    int           IsFastcall = 0; /* True if it's a fast call function */
     int           PtrOnStack = 0; /* True if a pointer copy is on stack */
 
     /* Skip the left paren */
@@ -444,7 +444,7 @@ static void FunctionCall (ExprDesc* Expr)
     if (IsFuncPtr) {
 
        /* Check wether it's a fastcall function that has parameters */
-       IsFastCall = IsFastCallFunc (Expr->Type + 1) && (Func->ParamCount > 0);
+       IsFastcall = IsQualFastcall (Expr->Type + 1) && (Func->ParamCount > 0);
 
        /* Things may be difficult, depending on where the function pointer
         * resides. If the function pointer is an expression of some sort
@@ -454,7 +454,7 @@ static void FunctionCall (ExprDesc* Expr)
         * For fastcall functions we do also need to place a copy of the
         * pointer on stack, since we cannot use a/x.
         */
-       PtrOnStack = IsFastCall || !ED_IsConst (Expr);
+       PtrOnStack = IsFastcall || !ED_IsConst (Expr);
        if (PtrOnStack) {
 
            /* Not a global or local variable, or a fastcall function. Load
@@ -471,18 +471,23 @@ static void FunctionCall (ExprDesc* Expr)
            PtrOffs = StackPtr;
        }
 
-    /* Check for known standard functions and inline them */
-    } else if (Expr->Name != 0) {
-        int StdFunc = FindStdFunc ((const char*) Expr->Name);
-        if (StdFunc >= 0) {
-            /* Inline this function */
-            HandleStdFunc (StdFunc, Func, Expr);
-            return;
+    } else {
+        /* Check for known standard functions and inline them */
+        if (Expr->Name != 0) {
+            int StdFunc = FindStdFunc ((const char*) Expr->Name);
+            if (StdFunc >= 0) {
+                /* Inline this function */
+                HandleStdFunc (StdFunc, Func, Expr);
+                return;
+            }
         }
+
+        /* If we didn't inline the function, get fastcall info */
+        IsFastcall = IsQualFastcall (Expr->Type);
     }
 
     /* Parse the parameter list */
-    ParamSize = FunctionParamList (Func);
+    ParamSize = FunctionParamList (Func, IsFastcall);
 
     /* We need the closing paren here */
     ConsumeRParen ();
@@ -493,7 +498,7 @@ static void FunctionCall (ExprDesc* Expr)
        /* If the function is not a fastcall function, load the pointer to
         * the function into the primary.
         */
-       if (!IsFastCall) {
+       if (!IsFastcall) {
 
            /* Not a fastcall function - we may use the primary */
                    if (PtrOnStack) {
@@ -1290,7 +1295,7 @@ static void PreInc (ExprDesc* Expr)
     }
 
     /* Result is an expression, no reference */
-    ED_MakeRValExpr (Expr);     
+    ED_MakeRValExpr (Expr);
 }
 
 
@@ -1367,7 +1372,7 @@ static void PreDec (ExprDesc* Expr)
 
     /* Result is an expression, no reference */
     ED_MakeRValExpr (Expr);
-}                               
+}
 
 
 
index 56da848a14629292d0f4e8b7b6790d4b68b69c4d..7186c3ee88fbdec7a99d5dfe1857a50a6b162d34 100644 (file)
 #define FD_EMPTY                       0x0001U /* Function with empty param list    */
 #define FD_VOID_PARAM          0x0002U /* Function with a void param list   */
 #define FD_VARIADIC            0x0004U /* Function with variable param list */
-#define FD_FASTCALL            0x0010U /* __fastcall__ function             */
-#define FD_FAR                 0x0020U /* __far__ function                  */
-#define FD_NEAR                        0x0040U /* __near__ function                 */
-#define FD_OLDSTYLE                    0x0100U /* Old style (K&R) function          */
-#define FD_OLDSTYLE_INTRET     0x0200U /* K&R func has implicit int return  */
-#define FD_UNNAMED_PARAMS              0x0400U /* Function has unnamed params       */
+#define FD_OLDSTYLE                    0x0010U /* Old style (K&R) function          */
+#define FD_OLDSTYLE_INTRET     0x0020U /* K&R func has implicit int return  */
+#define FD_UNNAMED_PARAMS              0x0040U /* Function has unnamed params       */
 
 /* Bits that must be ignored when comparing funcs */
 #define FD_IGNORE       (FD_OLDSTYLE | FD_OLDSTYLE_INTRET | FD_UNNAMED_PARAMS)
index 6a2a769127f3502e78a843e82d4332cc516bcc31..d278fc63a392c2d4b562fdcb1903fb0f05b776fe 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2006 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 2000-2008 Ullrich von Bassewitz                                       */
+/*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -370,7 +370,7 @@ void NewFunc (SymEntry* Func)
     /* Special handling for main() */
     if (strcmp (Func->Name, "main") == 0) {
         /* Main cannot be a fastcall function */
-        if (IsFastCallFunc (Func->Type)) {
+        if (IsQualFastcall (Func->Type)) {
             Error ("`main' cannot be declared as __fastcall__");
         }
 
@@ -391,7 +391,7 @@ void NewFunc (SymEntry* Func)
     }
 
     /* If this is a fastcall function, push the last parameter onto the stack */
-    if (IsFastCallFunc (Func->Type) && D->ParamCount > 0) {
+    if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
 
        unsigned Flags;
 
index 0752d60bac96c3c809a5393f1488c3d671d0fa0f..6afc6698f3a7255457f6803c51ff189f241ad4f2 100644 (file)
@@ -52,6 +52,7 @@ static void SetResult (typecmp_t* Result, typecmp_t Val)
 /* Set a new result value if it is less than the existing one */
 {
     if (Val < *Result) {
+        /* printf ("SetResult = %d\n", Val); */
        *Result = Val;
     }
 }
@@ -246,13 +247,14 @@ static void DoCompare (const Type* lhs, const Type* rhs, typecmp_t* Result)
                }
                if (LeftQual != RightQual) {
            /* On the first indirection level, different qualifiers mean
-            * that the types are still compatible. On the second level,
-            * this is a (maybe minor) error, so we create a special
-            * return code, since a qualifier is dropped from a pointer.
-            * Starting from the next level, the types are incompatible
-            * if the qualifiers differ.
-            */
-           switch (Indirections) {
+            * that the types are still compatible. On the second level,
+            * this is a (maybe minor) error, so we create a special
+            * return code, since a qualifier is dropped from a pointer.
+            * Starting from the next level, the types are incompatible
+            * if the qualifiers differ.
+            */
+            /* printf ("Ind = %d    %06X != %06X\n", Indirections, LeftQual, RightQual); */
+           switch (Indirections) {
 
                case 0:
                    SetResult (Result, TC_STRICT_COMPATIBLE);
index 7ef1e63ee29e070bc4adb68bedbab135ddc5d1d0..57313457db6a560562298e90348a3af51c48eb84 100644 (file)
@@ -168,11 +168,6 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
  * impossible.
  */
 {
-    /* Get the type of the right hand side. Treat function types as
-     * pointer-to-function
-     */
-    Expr->Type = PtrConversion (Expr->Type);
-
     /* First, do some type checking */
     if (IsTypeVoid (NewType) || IsTypeVoid (Expr->Type)) {
        /* If one of the sides are of type void, output a more apropriate
@@ -192,7 +187,10 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
 
         /* Handle conversions to int type */
                if (IsClassPtr (Expr->Type)) {
-           /* Pointer -> int conversion */
+           /* Pointer -> int conversion. Convert array to pointer */
+            if (IsTypeArray (Expr->Type)) {
+                Expr->Type = ArrayToPtr (Expr->Type);
+            }
            Warning ("Converting pointer to integer without a cast");
                } else if (!IsClassInt (Expr->Type) && !IsClassFloat (Expr->Type)) {
            Error ("Incompatible types");
@@ -207,7 +205,13 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
     } else if (IsClassPtr (NewType)) {
 
         /* Handle conversions to pointer type */
-       if (IsClassPtr (Expr->Type)) {
+               if (IsClassPtr (Expr->Type)) {
+
+            /* Convert array to pointer */
+            if (IsTypeArray (Expr->Type)) {
+                Expr->Type = ArrayToPtr (Expr->Type);
+            }
+
            /* Pointer to pointer assignment is valid, if:
             *   - both point to the same types, or
             *   - the rhs pointer is a void pointer, or
@@ -230,16 +234,20 @@ void TypeConversion (ExprDesc* Expr, Type* NewType)
                        break;
                }
            }
+
        } else if (IsClassInt (Expr->Type)) {
            /* Int to pointer assignment is valid only for constant zero */
            if (!ED_IsConstAbsInt (Expr) || Expr->IVal != 0) {
                Warning ("Converting integer to pointer without a cast");
            }
        } else if (IsTypeFuncPtr (NewType) && IsTypeFunc(Expr->Type)) {
+            /* Function -> Function pointer. First convert rhs to pointer */
+            Expr->Type = PointerTo (Expr->Type);
+
            /* Assignment of function to function pointer is allowed, provided
             * that both functions have the same parameter list.
             */
-           if (TypeCmp (Indirect (NewType), Expr->Type) < TC_EQUAL) {
+                   if (TypeCmp (NewType, Expr->Type) < TC_EQUAL) {
                Error ("Incompatible types");
            }
        } else {