]> git.sur5r.net Git - cc65/commitdiff
Added code to parse bit fields and enter them into the symbol table. They're
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 29 Aug 2009 17:38:53 +0000 (17:38 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 29 Aug 2009 17:38:53 +0000 (17:38 +0000)
not supported in code generation until now.

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

src/cc65/datatype.h
src/cc65/declare.c
src/cc65/expr.c
src/cc65/symentry.c
src/cc65/symentry.h
src/cc65/symtab.c
src/cc65/symtab.h

index ea211777207619df799905a532bd73a5cdb7cb35..f9dd78313dddd5a3a1180c01b86f834ce3c38cfe 100644 (file)
@@ -174,6 +174,16 @@ struct Type {
 #define SIZEOF_DOUBLE   (FP_D_Size())
 #define SIZEOF_PTR      2
 
+/* Bit sizes */
+#define CHAR_BITS       (8 * SIZEOF_CHAR)
+#define SHORT_BITS      (8 * SIZEOF_SHORT)
+#define INT_BITS        (8 * SIZEOF_INT)
+#define LONG_BITS       (8 * SIZEOF_LONG)
+#define LONGLONG_BITS   (8 * SIZEOF_LONGLONG)
+#define FLOAT_BITS      (8 * SIZEOF_FLOAT)
+#define DOUBLE_BITS     (8 * SIZEOF_DOUBLE)
+#define PTR_BITS        (8 * SIZEOF_PTR)
+
 /* Predefined type strings */
 extern Type type_schar[];
 extern Type type_uchar[];
index 09a3f0020689991668a10f45c4843d70624fa9b1..36fa272d28953bbf98469f22be98d6749803ca11 100644 (file)
@@ -447,14 +447,55 @@ static void ParseEnumDecl (void)
 
 
 
+static int ParseFieldWidth (Declaration* Decl)
+/* Parse an optional field width. Returns -1 if no field width is speficied,
+ * otherwise the width of the field.
+ */
+{
+    ExprDesc Expr;
+
+    if (CurTok.Tok != TOK_COLON) {
+        /* No bit-field declaration */
+        return -1;
+    }
+
+    /* Read the width */
+    NextToken ();
+    ConstAbsIntExpr (hie1, &Expr);
+    if (Expr.IVal < 0) {
+        Error ("Negative width in bit-field");
+        return -1;
+    }
+    if (Expr.IVal > INT_BITS) {
+        Error ("Width of bit-field exceeds its type");
+        return -1;
+    }
+    if (Expr.IVal == 0 && Decl->Ident[0] != '\0') {
+        Error ("Zero width for named bit-field");
+        return -1;
+    }
+    if (!IsTypeInt (Decl->Type)) {
+        /* Only integer types may be used for bit-fields */
+        Error ("Bit-field has invalid type");
+        return -1;
+    }
+
+    /* Return the field width */
+    return (int) Expr.IVal;
+}
+
+
+
 static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
 /* Parse a struct/union declaration. */
 {
 
     unsigned  StructSize;
     unsigned  FieldSize;
-    unsigned  Offs;
     int       FlexibleMember;
+    unsigned  Offs;
+    int       BitOffs;          /* Bit offset for bit-fields */
+    int       FieldWidth;       /* Width in bits, -1 if not a bit-field */
     SymTable* FieldTab;
     SymEntry* Entry;
 
@@ -486,6 +527,7 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
     /* Parse struct fields */
     FlexibleMember = 0;
     StructSize     = 0;
+    BitOffs        = 0;
     while (CurTok.Tok != TOK_RCURLY) {
 
        /* Get the type of the entry */
@@ -507,16 +549,52 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
             }
 
            /* Get type and name of the struct field */
-           ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
+           ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
+
+            /* Check for a bit-field declaration */
+            FieldWidth = ParseFieldWidth (&Decl);
 
-            /* Get the offset of this field */
-            Offs = (StructType == T_STRUCT)? StructSize : 0;
+            /* A non bit-field without a name is legal but useless */
+            if (FieldWidth < 0 && Decl.Ident[0] == '\0') {
+                Warning ("Declaration does not declare anything");
+                goto NextMember;
+            }
+
+            /* If this is not a bit field, or the bit field is too large for
+             * the remainder of the current member, or we have a bit field
+             * with width zero, align the struct to the next member
+             */
+            if (BitOffs > 0) {
+                if (FieldWidth <= 0 || (BitOffs + FieldWidth) > INT_BITS) {
+                    /* BitOffs > 0, so this can only be a struct */
+                    StructSize += SIZEOF_INT;
+                    BitOffs = 0;
+                }
+            }
+
+            /* Apart from the above, a bit field with width 0 is not processed
+             * further. An unnamed bit field will just increase the bit offset.
+             */
+            if (FieldWidth == 0) {
+                goto NextMember;
+            } else if (FieldWidth > 0 && Decl.Ident[0] == '\0') {
+                if (StructType == T_STRUCT) {
+                    BitOffs += FieldWidth;
+                }
+                goto NextMember;
+            }
 
             /* Calculate the sizes, handle flexible array members */
             if (StructType == T_STRUCT) {
 
-                /* It's a struct. Check if this field is a flexible array
-                 * member, and calculate the size of the field.
+                /* It's a struct. Offset of this member is the current struct
+                 * size plus any full bytes from the bit offset in case of
+                 * bit-fields.
+                 */
+                Offs = StructSize + (BitOffs >> 3);
+
+                /* Check if this field is a flexible array member, and
+                 * calculate the size of the field.
                  */
                 if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
                     /* Array with unspecified size */
@@ -526,28 +604,41 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
                     FlexibleMember = 1;
                     /* Assume zero for size calculations */
                     SetElementCount (Decl.Type, FLEXIBLE);
-                } else {
+                } else if (FieldWidth < 0) {
                     StructSize += CheckedSizeOf (Decl.Type);
                 }
 
-           } else {
+                /* Add a field entry to the table */
+                if (FieldWidth > 0) {
+                    AddBitField (Decl.Ident, Offs, BitOffs & 0x07, FieldWidth);
+                    BitOffs += FieldWidth;
+                } else {
+                    AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
+                }
+
+           } else {
 
-                /* It's a union */
+                /* It's a union. Offset of this member is always zero */
+                Offs = 0;
                 FieldSize = CheckedSizeOf (Decl.Type);
-               if (FieldSize > StructSize) {
-                   StructSize = FieldSize;
-               }
-           }
+               if (FieldSize > StructSize) {
+                   StructSize = FieldSize;
+               }
 
-           /* Add a field entry to the table */
-           AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
+                /* Add a field entry to the table */
+                if (FieldWidth > 0) {
+                    AddBitField (Decl.Ident, 0, 0, FieldWidth);
+                } else {
+                    AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
+                }
+           }
 
-           if (CurTok.Tok != TOK_COMMA) {
-               break;
+NextMember: if (CurTok.Tok != TOK_COMMA) {
+               break;
             }
-           NextToken ();
-       }
-       ConsumeSemi ();
+           NextToken ();
+       }
+       ConsumeSemi ();
     }
 
     /* Skip the closing brace */
index 6c6268cc1f52d4c1606334a0a6832fc402ec4213..1d5dd9ccdc7eb84c74b141a168f8fa01a4154607 100644 (file)
@@ -1066,6 +1066,11 @@ static void StructRef (ExprDesc* Expr)
        Error ("Struct/union has no field named `%s'", Ident);
                Expr->Type = type_int;
        return;
+    }       
+    if ((Field->Flags & SC_BITFIELD) == SC_BITFIELD) {
+        Error ("Bit-fields are currently unsupported - sorry");
+        Expr->Type = type_int;
+        return;
     }
 
     /* If we have a struct pointer that is an lvalue and not already in the
@@ -1884,8 +1889,8 @@ static void hie_compare (const GenDesc* Ops,    /* List of generators */
 
        /* Check for const operands */
        if (ED_IsConstAbs (Expr) && rconst) {
-             
-            /* If the result is constant, this is suspicious when not in 
+
+            /* If the result is constant, this is suspicious when not in
              * preprocessor mode.
              */
             if (!Preprocessing) {
index 230362b562afd3a0ae62eff9b87316dc4c6fdda5..718cd470e7e0489caca3274cd8c06ff938645940 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2006 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -95,6 +95,7 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
     } Flags [] = {
        /* Beware: Order is important! */
        { "SC_TYPEDEF",     SC_TYPEDEF          },
+        { "SC_BITFIELD",    SC_BITFIELD         },
                { "SC_STRUCTFIELD", SC_STRUCTFIELD      },
        { "SC_STRUCT",      SC_STRUCT           },
        { "SC_AUTO",        SC_AUTO             },
index a43356cc9e0ac73af5a6a532114b8f6d0903ef42..d9139a8b7870b7a56c44d02bb5c6eea0a92b26c1 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2008 Ullrich von Bassewitz                                       */
+/* (C) 2000-2009 Ullrich von Bassewitz                                       */
 /*               Roemerstrasse 52                                            */
 /*               D-70794 Filderstadt                                         */
 /* EMail:        uz@cc65.org                                                 */
@@ -86,7 +86,8 @@ struct Segments;
 #define SC_TYPE                0x4000U /* This is a type, struct, typedef, etc. */
 #define SC_STRUCT              0x4001U /* Struct or union */
 #define SC_STRUCTFIELD  0x4002U        /* Struct or union field */
-#define SC_TYPEDEF             0x4003U /* A typedef */
+#define SC_BITFIELD     0x4004U /* A bit-field inside a struct or union */
+#define SC_TYPEDEF             0x4008U /* A typedef */
 
 #define SC_ZEROPAGE    0x8000U /* Symbol marked as zeropage */
 
@@ -130,6 +131,13 @@ struct SymEntry {
            unsigned            Size;     /* Size of the union/struct */
        } S;
 
+        /* Data for bit fields */
+        struct {
+            unsigned            Offs;     /* Byte offset into struct */
+            unsigned            BitOffs;  /* Bit offset into last byte */
+            unsigned            Width;    /* Width in bits */
+        } B;
+
        /* Data for functions */
        struct {
            struct FuncDesc*    Func;     /* Function descriptor */
index 0a03cabcaa0a426175e47ff3e98d9346435875af..c3ca6ba9406c07ce2230d400d38f3f088d400c07 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2006 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -485,19 +485,14 @@ SymEntry* FindStructField (const Type* T, const char* Name)
     /* Non-structs do not have any struct fields... */
     if (IsClassStruct (T)) {
 
-       const SymTable* Tab;
-
        /* Get a pointer to the struct/union type */
        const SymEntry* Struct = GetSymEntry (T);
        CHECK (Struct != 0);
 
-       /* Get the field symbol table from the struct entry.
-        * Beware: The table may not exist.
+       /* Now search in the struct symbol table. Beware: The table may not
+         * exist.
         */
-       Tab = Struct->V.S.SymTab;
-
-       /* Now search in the struct symbol table */
-       if (Tab) {
+       if (Struct->V.S.SymTab) {
                    Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
        }
     }
@@ -582,6 +577,38 @@ SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab)
 
 
 
+SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width)
+/* Add a bit field to the local symbol table and return the symbol entry */
+{
+    /* Do we have an entry with this name already? */
+    SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
+    if (Entry) {
+
+       /* We have a symbol with this name already */
+       Error ("Multiple definition for `%s'", Name);
+
+    } else {
+
+       /* Create a new entry */
+       Entry = NewSymEntry (Name, SC_BITFIELD);
+
+       /* Set the symbol attributes. Bit-fields are always of type unsigned */
+       Entry->Type        = type_uint;
+        Entry->V.B.Offs    = Offs;
+        Entry->V.B.BitOffs = BitOffs;
+        Entry->V.B.Width   = Width;
+
+       /* Add the entry to the symbol table */
+       AddSymEntry (SymTab, Entry);
+
+    }
+
+    /* Return the entry */
+    return Entry;
+}
+
+
+
 SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val)
 /* Add an constant symbol to the symbol table and return it */
 {
index f3d3656a06b5b296602baeb8cbd4a24b11af1c34..18c8ce141115971d91bcde96429f77ec8f277868 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000     Ullrich von Bassewitz                                        */
-/*              Wacholderweg 14                                              */
-/*              D-70597 Stuttgart                                            */
-/* EMail:       uz@musoftware.de                                             */
+/* (C) 2000-2009, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -147,6 +147,9 @@ SymEntry* FindStructField (const Type* TypeArray, const char* Name);
 SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab);
 /* Add a struct/union entry and return it */
 
+SymEntry* AddBitField (const char* Name, unsigned Offs, unsigned BitOffs, unsigned Width);
+/* Add a bit field to the local symbol table and return the symbol entry */
+
 SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val);
 /* Add an constant symbol to the symbol table and return it */