]> git.sur5r.net Git - cc65/blobdiff - src/cc65/declare.c
Optimization for __bzero.
[cc65] / src / cc65 / declare.c
index 59a618dac423253696cfedd9b3b688d0cad1b416..9f0a94a27d9f267b4fadc266d0fdd5222e44a5b8 100644 (file)
@@ -6,8 +6,8 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
+/* (C) 1998-2004 Ullrich von Bassewitz                                       */
+/*               Römerstraße 52                                              */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
 /*                                                                           */
@@ -38,6 +38,8 @@
 #include <errno.h>
 
 /* common */
+#include "addrsize.h"
+#include "mmodel.h"
 #include "xmalloc.h"
 
 /* cc65 */
@@ -422,7 +424,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
                optionalsigned ();
                optionalint ();
                D->Type[0] = T_SHORT;
-               D->Type[1] = T_END;
+               D->Type[1] = T_END;
            }
            break;
 
@@ -460,7 +462,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
                    NextToken ();
                    /* FALL THROUGH */
 
-               default:
+               default:
                    D->Type[0] = T_INT;
                    D->Type[1] = T_END;
                    break;
@@ -502,6 +504,18 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
            }
            break;
 
+        case TOK_FLOAT:
+           NextToken ();
+           D->Type[0] = T_FLOAT;
+           D->Type[1] = T_END;
+           break;
+
+        case TOK_DOUBLE:
+           NextToken ();
+           D->Type[0] = T_DOUBLE;
+           D->Type[1] = T_END;
+           break;
+
        case TOK_STRUCT:
        case TOK_UNION:
            StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
@@ -831,6 +845,13 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
        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);
 
@@ -840,39 +861,114 @@ static FuncDesc* ParseFuncDecl (const DeclSpec* Spec)
 
 
 
+static unsigned FunctionModifierFlags (void)
+/* Parse __fastcall__, __near__ and __far__ and return the matching FD_ flags */
+{
+    /* 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;
+}
+
+
+
+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;
+    }
+
+    /* 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) {
-       type T = T_PTR;
+
+       type T;
+
+        /* Skip the star */
                NextToken ();
+
        /* Allow optional const or volatile qualifiers */
-       T |= OptionalQualifiers (T_QUAL_NONE);
+               T = T_PTR | OptionalQualifiers (T_QUAL_NONE);
+
+        /* Parse the type, the pointer points to */
                Decl (Spec, D, Mode);
+
                *D->T++ = T;
                return;
-    } else if (CurTok.Tok == TOK_LPAREN) {
-               NextToken ();
-               Decl (Spec, D, Mode);
-               ConsumeRParen ();
-    } else if (CurTok.Tok == TOK_FASTCALL) {
+    }
+
+    /* Function modifiers */
+    if (CurTok.Tok == TOK_FASTCALL || CurTok.Tok == TOK_NEAR || CurTok.Tok == TOK_FAR) {
+
        /* Remember the current type pointer */
        type* T = D->T;
-       /* Skip the fastcall token */
-       NextToken ();
+
+       /* Read the flags */
+       unsigned Flags = FunctionModifierFlags ();
+
        /* Parse the function */
        Decl (Spec, D, Mode);
-       /* Set the fastcall flag */
+
+       /* Check that we have a function */
        if (!IsTypeFunc (T) && !IsTypeFuncPtr (T)) {
-           Error ("__fastcall__ modifier applied to non function");
-       } else if (IsVariadicFunc (T)) {
-           Error ("Cannot apply __fastcall__ to functions with variable parameter list");
+           Error ("Function modifier applied to non function");
        } else {
-           FuncDesc* F = GetFuncDesc (T);
-                   F->Flags |= FD_FASTCALL;
-       }
+            ApplyFunctionModifiers (T, Flags);
+        }
+
+       /* Done */
        return;
+    }
+
+    if (CurTok.Tok == TOK_LPAREN) {
+               NextToken ();
+               Decl (Spec, D, Mode);
+               ConsumeRParen ();
     } else {
        /* Things depend on Mode now:
                 *  - Mode == DM_NEED_IDENT means:
@@ -952,7 +1048,6 @@ type* ParseType (type* Type)
     ParseTypeSpec (&Spec, -1);
 
     /* Parse additional declarators */
-    InitDeclaration (&Decl);
     ParseDecl (&Spec, &Decl, DM_NO_IDENT);
 
     /* Copy the type to the target buffer */