Added code to parse bit fields and enter them into the symbol table. They're
not supported in code generation until now. git-svn-id: svn://svn.cc65.org/cc65/trunk@4072 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
82919fa2f8
commit
bd872a6324
7 changed files with 189 additions and 44 deletions
|
@ -174,6 +174,16 @@ struct Type {
|
||||||
#define SIZEOF_DOUBLE (FP_D_Size())
|
#define SIZEOF_DOUBLE (FP_D_Size())
|
||||||
#define SIZEOF_PTR 2
|
#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 */
|
/* Predefined type strings */
|
||||||
extern Type type_schar[];
|
extern Type type_schar[];
|
||||||
extern Type type_uchar[];
|
extern Type type_uchar[];
|
||||||
|
|
|
@ -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)
|
static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
|
||||||
/* Parse a struct/union declaration. */
|
/* Parse a struct/union declaration. */
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned StructSize;
|
unsigned StructSize;
|
||||||
unsigned FieldSize;
|
unsigned FieldSize;
|
||||||
unsigned Offs;
|
|
||||||
int FlexibleMember;
|
int FlexibleMember;
|
||||||
|
unsigned Offs;
|
||||||
|
int BitOffs; /* Bit offset for bit-fields */
|
||||||
|
int FieldWidth; /* Width in bits, -1 if not a bit-field */
|
||||||
SymTable* FieldTab;
|
SymTable* FieldTab;
|
||||||
SymEntry* Entry;
|
SymEntry* Entry;
|
||||||
|
|
||||||
|
@ -486,6 +527,7 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
|
||||||
/* Parse struct fields */
|
/* Parse struct fields */
|
||||||
FlexibleMember = 0;
|
FlexibleMember = 0;
|
||||||
StructSize = 0;
|
StructSize = 0;
|
||||||
|
BitOffs = 0;
|
||||||
while (CurTok.Tok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
|
|
||||||
/* Get the type of the entry */
|
/* 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 */
|
/* Get type and name of the struct field */
|
||||||
ParseDecl (&Spec, &Decl, DM_NEED_IDENT);
|
ParseDecl (&Spec, &Decl, DM_ACCEPT_IDENT);
|
||||||
|
|
||||||
/* Get the offset of this field */
|
/* Check for a bit-field declaration */
|
||||||
Offs = (StructType == T_STRUCT)? StructSize : 0;
|
FieldWidth = ParseFieldWidth (&Decl);
|
||||||
|
|
||||||
|
/* 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 */
|
/* Calculate the sizes, handle flexible array members */
|
||||||
if (StructType == T_STRUCT) {
|
if (StructType == T_STRUCT) {
|
||||||
|
|
||||||
/* It's a struct. Check if this field is a flexible array
|
/* It's a struct. Offset of this member is the current struct
|
||||||
* member, and calculate the size of the field.
|
* 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) {
|
if (IsTypeArray (Decl.Type) && GetElementCount (Decl.Type) == UNSPECIFIED) {
|
||||||
/* Array with unspecified size */
|
/* Array with unspecified size */
|
||||||
|
@ -526,23 +604,36 @@ static SymEntry* ParseStructDecl (const char* Name, TypeCode StructType)
|
||||||
FlexibleMember = 1;
|
FlexibleMember = 1;
|
||||||
/* Assume zero for size calculations */
|
/* Assume zero for size calculations */
|
||||||
SetElementCount (Decl.Type, FLEXIBLE);
|
SetElementCount (Decl.Type, FLEXIBLE);
|
||||||
} else {
|
} else if (FieldWidth < 0) {
|
||||||
StructSize += CheckedSizeOf (Decl.Type);
|
StructSize += CheckedSizeOf (Decl.Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 {
|
} else {
|
||||||
|
|
||||||
/* It's a union */
|
/* It's a union. Offset of this member is always zero */
|
||||||
|
Offs = 0;
|
||||||
FieldSize = CheckedSizeOf (Decl.Type);
|
FieldSize = CheckedSizeOf (Decl.Type);
|
||||||
if (FieldSize > StructSize) {
|
if (FieldSize > StructSize) {
|
||||||
StructSize = FieldSize;
|
StructSize = FieldSize;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Add a field entry to the table */
|
/* 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);
|
AddLocalSym (Decl.Ident, Decl.Type, SC_STRUCTFIELD, Offs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (CurTok.Tok != TOK_COMMA) {
|
NextMember: if (CurTok.Tok != TOK_COMMA) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
|
@ -1067,6 +1067,11 @@ static void StructRef (ExprDesc* Expr)
|
||||||
Expr->Type = type_int;
|
Expr->Type = type_int;
|
||||||
return;
|
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
|
/* If we have a struct pointer that is an lvalue and not already in the
|
||||||
* primary, load it now.
|
* primary, load it now.
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2006 Ullrich von Bassewitz */
|
/* (C) 2000-2009, Ullrich von Bassewitz */
|
||||||
/* Römerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
|
@ -95,6 +95,7 @@ void DumpSymEntry (FILE* F, const SymEntry* E)
|
||||||
} Flags [] = {
|
} Flags [] = {
|
||||||
/* Beware: Order is important! */
|
/* Beware: Order is important! */
|
||||||
{ "SC_TYPEDEF", SC_TYPEDEF },
|
{ "SC_TYPEDEF", SC_TYPEDEF },
|
||||||
|
{ "SC_BITFIELD", SC_BITFIELD },
|
||||||
{ "SC_STRUCTFIELD", SC_STRUCTFIELD },
|
{ "SC_STRUCTFIELD", SC_STRUCTFIELD },
|
||||||
{ "SC_STRUCT", SC_STRUCT },
|
{ "SC_STRUCT", SC_STRUCT },
|
||||||
{ "SC_AUTO", SC_AUTO },
|
{ "SC_AUTO", SC_AUTO },
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2008 Ullrich von Bassewitz */
|
/* (C) 2000-2009 Ullrich von Bassewitz */
|
||||||
/* Roemerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
|
@ -86,7 +86,8 @@ struct Segments;
|
||||||
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
|
#define SC_TYPE 0x4000U /* This is a type, struct, typedef, etc. */
|
||||||
#define SC_STRUCT 0x4001U /* Struct or union */
|
#define SC_STRUCT 0x4001U /* Struct or union */
|
||||||
#define SC_STRUCTFIELD 0x4002U /* Struct or union field */
|
#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 */
|
#define SC_ZEROPAGE 0x8000U /* Symbol marked as zeropage */
|
||||||
|
|
||||||
|
@ -130,6 +131,13 @@ struct SymEntry {
|
||||||
unsigned Size; /* Size of the union/struct */
|
unsigned Size; /* Size of the union/struct */
|
||||||
} S;
|
} 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 */
|
/* Data for functions */
|
||||||
struct {
|
struct {
|
||||||
struct FuncDesc* Func; /* Function descriptor */
|
struct FuncDesc* Func; /* Function descriptor */
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000-2006 Ullrich von Bassewitz */
|
/* (C) 2000-2009, Ullrich von Bassewitz */
|
||||||
/* Römerstrasse 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
|
@ -485,19 +485,14 @@ SymEntry* FindStructField (const Type* T, const char* Name)
|
||||||
/* Non-structs do not have any struct fields... */
|
/* Non-structs do not have any struct fields... */
|
||||||
if (IsClassStruct (T)) {
|
if (IsClassStruct (T)) {
|
||||||
|
|
||||||
const SymTable* Tab;
|
|
||||||
|
|
||||||
/* Get a pointer to the struct/union type */
|
/* Get a pointer to the struct/union type */
|
||||||
const SymEntry* Struct = GetSymEntry (T);
|
const SymEntry* Struct = GetSymEntry (T);
|
||||||
CHECK (Struct != 0);
|
CHECK (Struct != 0);
|
||||||
|
|
||||||
/* Get the field symbol table from the struct entry.
|
/* Now search in the struct symbol table. Beware: The table may not
|
||||||
* Beware: The table may not exist.
|
* exist.
|
||||||
*/
|
*/
|
||||||
Tab = Struct->V.S.SymTab;
|
if (Struct->V.S.SymTab) {
|
||||||
|
|
||||||
/* Now search in the struct symbol table */
|
|
||||||
if (Tab) {
|
|
||||||
Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name));
|
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)
|
SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val)
|
||||||
/* Add an constant symbol to the symbol table and return it */
|
/* Add an constant symbol to the symbol table and return it */
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 2000 Ullrich von Bassewitz */
|
/* (C) 2000-2009, Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* 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);
|
SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab);
|
||||||
/* Add a struct/union entry and return it */
|
/* 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);
|
SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val);
|
||||||
/* Add an constant symbol to the symbol table and return it */
|
/* Add an constant symbol to the symbol table and return it */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue