#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[];
+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;
/* Parse struct fields */
FlexibleMember = 0;
StructSize = 0;
+ BitOffs = 0;
while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */
}
/* 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 */
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 */
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
/* 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) {
/* */
/* */
/* */
-/* (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 */
} 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 },
/* */
/* */
/* */
-/* (C) 2000-2008 Ullrich von Bassewitz */
+/* (C) 2000-2009 Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
#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 */
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 */
/* */
/* */
/* */
-/* (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 */
/* 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));
}
}
+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 */
{
/* */
/* */
/* */
-/* (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 */
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 */