X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fsymtab.c;h=56196ea5a3e82b03d441b80a971ef06e75dee932;hb=41e449b306ca207052a481e7be505a4fc490708c;hp=3bab90d7c01bb838937a6e56f3648ce55cc500ed;hpb=cd6f591d1111a6f746e0a5f5f342efeb8b776220;p=cc65 diff --git a/src/cc65/symtab.c b/src/cc65/symtab.c index 3bab90d7c..56196ea5a 100644 --- a/src/cc65/symtab.c +++ b/src/cc65/symtab.c @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* symtab.c */ +/* symtab.c */ /* */ -/* Symbol table management for the cc65 C compiler */ +/* Symbol table management for the cc65 C compiler */ /* */ /* */ /* */ -/* (C) 2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 2000-2013, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -40,7 +40,8 @@ /* common */ #include "check.h" -#include "hashstr.h" +#include "debugflag.h" +#include "hashfunc.h" #include "xmalloc.h" /* cc65 */ @@ -52,50 +53,50 @@ #include "error.h" #include "funcdesc.h" #include "global.h" +#include "stackptr.h" #include "symentry.h" #include "typecmp.h" #include "symtab.h" +#include "function.h" +#include "input.h" /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ /* An empty symbol table */ -SymTable EmptySymTab = { - 0, /* PrevTab */ - 0, /* SymHead */ - 0, /* SymTail */ - 0, /* SymCount */ - 1, /* Size */ - { 0 } /* Tab[1] */ +SymTable EmptySymTab = { + 0, /* PrevTab */ + 0, /* SymHead */ + 0, /* SymTail */ + 0, /* SymCount */ + 1, /* Size */ + { 0 } /* Tab[1] */ }; /* Symbol table sizes */ -#define SYMTAB_SIZE_GLOBAL 211U -#define SYMTAB_SIZE_FUNCTION 29U -#define SYMTAB_SIZE_BLOCK 13U -#define SYMTAB_SIZE_STRUCT 19U -#define SYMTAB_SIZE_LABEL 7U - -/* Predefined lexical levels */ -#define LEX_LEVEL_GLOBAL 1U +#define SYMTAB_SIZE_GLOBAL 211U +#define SYMTAB_SIZE_FUNCTION 29U +#define SYMTAB_SIZE_BLOCK 13U +#define SYMTAB_SIZE_STRUCT 19U +#define SYMTAB_SIZE_LABEL 7U /* The current and root symbol tables */ -static unsigned LexicalLevel = 0; /* For safety checks */ -static SymTable* SymTab0 = 0; -static SymTable* SymTab = 0; -static SymTable* TagTab0 = 0; -static SymTable* TagTab = 0; -static SymTable* LabelTab = 0; - +static unsigned LexicalLevel = 0; /* For safety checks */ +static SymTable* SymTab0 = 0; +static SymTable* SymTab = 0; +static SymTable* TagTab0 = 0; +static SymTable* TagTab = 0; +static SymTable* LabelTab = 0; +static SymTable* SPAdjustTab = 0; /*****************************************************************************/ -/* struct SymTable */ +/* struct SymTable */ /*****************************************************************************/ @@ -109,13 +110,13 @@ static SymTable* NewSymTable (unsigned Size) SymTable* S = xmalloc (sizeof (SymTable) + (Size-1) * sizeof (SymEntry*)); /* Initialize the symbol table structure */ - S->PrevTab = 0; - S->SymHead = 0; - S->SymTail = 0; - S->SymCount = 0; - S->Size = Size; + S->PrevTab = 0; + S->SymHead = 0; + S->SymTail = 0; + S->SymCount = 0; + S->Size = Size; for (I = 0; I < Size; ++I) { - S->Tab[I] = 0; + S->Tab[I] = 0; } /* Return the symbol table */ @@ -130,9 +131,9 @@ static void FreeSymTable (SymTable* S) /* Free all symbols */ SymEntry* Sym = S->SymHead; while (Sym) { - SymEntry* NextSym = Sym->NextSym; - FreeSymEntry (Sym); - Sym = NextSym; + SymEntry* NextSym = Sym->NextSym; + FreeSymEntry (Sym); + Sym = NextSym; } /* Free the table itself */ @@ -142,7 +143,7 @@ static void FreeSymTable (SymTable* S) /*****************************************************************************/ -/* Check symbols in a table */ +/* Check symbols in a table */ /*****************************************************************************/ @@ -153,51 +154,66 @@ static void CheckSymTable (SymTable* Tab) SymEntry* Entry = Tab->SymHead; while (Entry) { - /* Get the storage flags for tne entry */ - unsigned Flags = Entry->Flags; - - /* Ignore typedef entries */ - if ((Flags & SC_TYPEDEF) != SC_TYPEDEF) { - - /* Check if the symbol is one with storage, and it if it was - * defined but not used. - */ - if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) { - if ((Flags & SC_DEF) && !(Flags & SC_REF)) { - if (Flags & SC_PARAM) { - Warning ("Parameter `%s' is never used", Entry->Name); - } else { - Warning ("`%s' is defined but never used", Entry->Name); - } - } - } - - /* If the entry is a label, check if it was defined in the function */ - if (Flags & SC_LABEL) { - if ((Flags & SC_DEF) == 0) { - /* Undefined label */ - Error ("Undefined label: `%s'", Entry->Name); - } else if ((Flags & SC_REF) == 0) { - /* Defined but not used */ - Warning ("`%s' is defined but never used", Entry->Name); - } - } - - } - - /* Next entry */ - Entry = Entry->NextSym; + /* Get the storage flags for tne entry */ + unsigned Flags = Entry->Flags; + + /* Ignore typedef entries */ + if (!SymIsTypeDef (Entry)) { + + /* Check if the symbol is one with storage, and it if it was + ** defined but not used. + */ + if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) { + if (SymIsDef (Entry) && !SymIsRef (Entry) && + !SymHasAttr (Entry, atUnused)) { + if (Flags & SC_PARAM) { + if (IS_Get (&WarnUnusedParam)) { + Warning ("Parameter '%s' is never used", Entry->Name); + } + } else { + if (IS_Get (&WarnUnusedVar)) { + Warning ("'%s' is defined but never used", Entry->Name); + } + } + } + } + + /* If the entry is a label, check if it was defined in the function */ + if (Flags & SC_LABEL) { + if (!SymIsDef (Entry)) { + /* Undefined label */ + Error ("Undefined label: '%s'", Entry->Name); + } else if (!SymIsRef (Entry)) { + /* Defined but not used */ + if (IS_Get (&WarnUnusedLabel)) { + Warning ("'%s' is defined but never used", Entry->Name); + } + } + } + + } + + /* Next entry */ + Entry = Entry->NextSym; } } /*****************************************************************************/ -/* Handling of lexical levels */ +/* Handling of lexical levels */ /*****************************************************************************/ +unsigned GetLexicalLevel (void) +/* Return the current lexical level */ +{ + return LexicalLevel; +} + + + void EnterGlobalLevel (void) /* Enter the program global lexical level */ { @@ -209,6 +225,9 @@ void EnterGlobalLevel (void) /* Create and assign the tag table */ TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL); + + /* Create and assign the table of SP adjustment symbols */ + SPAdjustTab = NewSymTable (SYMTAB_SIZE_GLOBAL); } @@ -224,13 +243,13 @@ void LeaveGlobalLevel (void) /* Dump the tables if requested */ if (Debug) { - PrintSymTable (SymTab0, stdout, "Global symbol table"); - PrintSymTable (TagTab0, stdout, "Global tag table"); + PrintSymTable (SymTab0, stdout, "Global symbol table"); + PrintSymTable (TagTab0, stdout, "Global tag table"); } /* Don't delete the symbol and struct tables! */ - SymTab0 = SymTab = 0; - TagTab0 = TagTab = 0; + SymTab = 0; + TagTab = 0; } @@ -254,7 +273,9 @@ void EnterFunctionLevel (void) TagTab = S; /* Create and assign a new label table */ - LabelTab = NewSymTable (SYMTAB_SIZE_LABEL); + S = NewSymTable (SYMTAB_SIZE_LABEL); + S->PrevTab = LabelTab; + LabelTab = S; } @@ -272,6 +293,7 @@ void RememberFunctionLevel (struct FuncDesc* F) /* Don't delete the tables */ SymTab = SymTab->PrevTab; TagTab = TagTab->PrevTab; + LabelTab = LabelTab->PrevTab; } @@ -307,7 +329,7 @@ void LeaveFunctionLevel (void) /* Drop the label table if it is empty */ if (LabelTab->SymCount == 0) { - FreeSymTable (LabelTab); + FreeSymTable (LabelTab); } /* Don't delete the tables */ @@ -328,8 +350,8 @@ void EnterBlockLevel (void) /* Get a new symbol table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); - S->PrevTab = SymTab; - SymTab = S; + S->PrevTab = SymTab; + SymTab = S; /* Get a new tag table and make it current */ S = NewSymTable (SYMTAB_SIZE_BLOCK); @@ -361,12 +383,12 @@ void EnterStructLevel (void) SymTable* S; /* Get a new symbol table and make it current. Note: Structs and enums - * nested in struct scope are NOT local to the struct but visible in the - * outside scope. So we will NOT create a new struct or enum table. - */ + ** nested in struct scope are NOT local to the struct but visible in the + ** outside scope. So we will NOT create a new struct or enum table. + */ S = NewSymTable (SYMTAB_SIZE_BLOCK); - S->PrevTab = SymTab; - SymTab = S; + S->PrevTab = SymTab; + SymTab = S; } @@ -381,7 +403,7 @@ void LeaveStructLevel (void) /*****************************************************************************/ -/* Find functions */ +/* Find functions */ /*****************************************************************************/ @@ -392,13 +414,13 @@ static SymEntry* FindSymInTable (const SymTable* T, const char* Name, unsigned H /* Get the start of the hash chain */ SymEntry* E = T->Tab [Hash % T->Size]; while (E) { - /* Compare the name */ - if (strcmp (E->Name, Name) == 0) { - /* Found */ - return E; - } - /* Not found, next entry in hash chain */ - E = E->NextHash; + /* Compare the name */ + if (strcmp (E->Name, Name) == 0) { + /* Found */ + return E; + } + /* Not found, next entry in hash chain */ + E = E->NextHash; } /* Not found */ @@ -415,16 +437,16 @@ static SymEntry* FindSymInTree (const SymTable* Tab, const char* Name) /* Check all symbol tables for the symbol */ while (Tab) { - /* Try to find the symbol in this table */ - SymEntry* E = FindSymInTable (Tab, Name, Hash); + /* Try to find the symbol in this table */ + SymEntry* E = FindSymInTable (Tab, Name, Hash); - /* Bail out if we found it */ - if (E != 0) { - return E; - } + /* Bail out if we found it */ + if (E != 0) { + return E; + } - /* Repeat the search in the next higher lexical level */ - Tab = Tab->PrevTab; + /* Repeat the search in the next higher lexical level */ + Tab = Tab->PrevTab; } /* Not found */ @@ -441,6 +463,14 @@ SymEntry* FindSym (const char* Name) +SymEntry* FindGlobalSym (const char* Name) +/* Find the symbol with the given name in the global symbol table only */ +{ + return FindSymInTable (SymTab0, Name, HashStr (Name)); +} + + + SymEntry* FindLocalSym (const char* Name) /* Find the symbol with the given name in the current symbol table only */ { @@ -457,34 +487,29 @@ SymEntry* FindTagSym (const char* Name) -SymEntry* FindStructField (const type* Type, const char* Name) +SymEntry* FindStructField (const Type* T, const char* Name) /* Find a struct field in the fields list */ { SymEntry* Field = 0; /* The given type may actually be a pointer to struct */ - if (Type[0] == T_PTR) { - ++Type; + if (IsTypePtr (T)) { + ++T; } /* Non-structs do not have any struct fields... */ - if (IsClassStruct (Type)) { - - const SymTable* Tab; - - /* Get a pointer to the struct/union type */ - const SymEntry* Struct = (const SymEntry*) Decode (Type+1); - CHECK (Struct != 0); - - /* Get the field symbol table from the struct entry. - * Beware: The table may not exist. - */ - Tab = Struct->V.S.SymTab; - - /* Now search in the struct symbol table */ - if (Tab) { - Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); - } + if (IsClassStruct (T)) { + + /* Get a pointer to the struct/union type */ + const SymEntry* Struct = GetSymEntry (T); + CHECK (Struct != 0); + + /* Now search in the struct symbol table. Beware: The table may not + ** exist. + */ + if (Struct->V.S.SymTab) { + Field = FindSymInTable (Struct->V.S.SymTab, Name, HashStr (Name)); + } } return Field; @@ -493,7 +518,7 @@ SymEntry* FindStructField (const type* Type, const char* Name) /*****************************************************************************/ -/* Add stuff to the symbol table */ +/* Add stuff to the symbol table */ /*****************************************************************************/ @@ -506,15 +531,15 @@ static void AddSymEntry (SymTable* T, SymEntry* S) /* Insert the symbol into the list of all symbols in this level */ if (T->SymTail) { - T->SymTail->NextSym = S; + T->SymTail->NextSym = S; } S->PrevSym = T->SymTail; T->SymTail = S; if (T->SymHead == 0) { - /* First symbol */ - T->SymHead = S; + /* First symbol */ + T->SymHead = S; } - T->SymCount++; + ++T->SymCount; /* Insert the symbol into the hash chain */ S->NextHash = T->Tab[Hash]; @@ -526,39 +551,44 @@ static void AddSymEntry (SymTable* T, SymEntry* S) -SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab) +SymEntry* AddStructSym (const char* Name, unsigned Type, unsigned Size, SymTable* Tab) /* Add a struct/union entry and return it */ { + SymEntry* Entry; + + /* Type must be struct or union */ + PRECONDITION (Type == SC_STRUCT || Type == SC_UNION); + /* Do we have an entry with this name already? */ - SymEntry* Entry = FindSymInTable (TagTab, Name, HashStr (Name)); + Entry = FindSymInTable (TagTab, Name, HashStr (Name)); if (Entry) { - /* We do have an entry. This may be a forward, so check it. */ - if ((Entry->Flags & SC_STRUCT) == 0) { - /* Existing symbol is not a struct */ - Error ("Symbol `%s' is already different kind", Name); - } else if (Size > 0 && Entry->V.S.Size > 0) { - /* Both structs are definitions. */ - Error ("Multiple definition for `%s'", Name); - } else { - /* Define the struct size if it is given */ - if (Size > 0) { - Entry->V.S.SymTab = Tab; - Entry->V.S.Size = Size; - } - } + /* We do have an entry. This may be a forward, so check it. */ + if ((Entry->Flags & SC_TYPEMASK) != Type) { + /* Existing symbol is not a struct */ + Error ("Symbol '%s' is already different kind", Name); + } else if (Size > 0 && Entry->V.S.Size > 0) { + /* Both structs are definitions. */ + Error ("Multiple definition for '%s'", Name); + } else { + /* Define the struct size if it is given */ + if (Size > 0) { + Entry->V.S.SymTab = Tab; + Entry->V.S.Size = Size; + } + } } else { - /* Create a new entry */ - Entry = NewSymEntry (Name, SC_STRUCT); + /* Create a new entry */ + Entry = NewSymEntry (Name, Type); - /* Set the struct data */ - Entry->V.S.SymTab = Tab; - Entry->V.S.Size = Size; + /* Set the struct data */ + Entry->V.S.SymTab = Tab; + Entry->V.S.Size = Size; - /* Add it to the current table */ - AddSymEntry (TagTab, Entry); + /* Add it to the current table */ + AddSymEntry (TagTab, Entry); } /* Return the entry */ @@ -567,91 +597,247 @@ SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab) -SymEntry* AddEnumSym (const char* Name, int Val) -/* Add an enum symbol to the symbol table 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 */ { /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name)); if (Entry) { - if (Entry->Flags != SC_ENUM) { - Error ("Symbol `%s' is already different kind", Name); - } else { - Error ("Multiple definition for `%s'", Name); - } - return 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.BitWidth = 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 */ +{ + /* Enums must be inserted in the global symbol table */ + SymTable* Tab = ((Flags & SC_ENUM) == SC_ENUM)? SymTab0 : SymTab; + + /* Do we have an entry with this name already? */ + SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); + if (Entry) { + if ((Entry->Flags & SC_CONST) != SC_CONST) { + Error ("Symbol '%s' is already different kind", Name); + } else { + Error ("Multiple definition for '%s'", Name); + } + return Entry; } /* Create a new entry */ - Entry = NewSymEntry (Name, SC_ENUM); + Entry = NewSymEntry (Name, Flags); /* Enum values are ints */ - Entry->Type = TypeDup (type_int); + Entry->Type = TypeDup (T); /* Set the enum data */ - Entry->V.EnumVal = Val; + Entry->V.ConstVal = Val; /* Add the entry to the symbol table */ - AddSymEntry (SymTab, Entry); + AddSymEntry (Tab, Entry); /* Return the entry */ return Entry; } +DefOrRef* AddDefOrRef (SymEntry* E, unsigned Flags) +/* Add definition or reference to the SymEntry and preserve its attributes */ +{ + DefOrRef *DOR; + + DOR = xmalloc (sizeof (DefOrRef)); + CollAppend (E->V.L.DefsOrRefs, DOR); + DOR->Line = GetCurrentLine (); + DOR->LocalsBlockId = (long)CollLast (&CurrentFunc->LocalsBlockStack); + DOR->Flags = Flags; + DOR->StackPtr = StackPtr; + DOR->Depth = CollCount (&CurrentFunc->LocalsBlockStack); + DOR->LateSP_Label = GetLocalLabel (); + + return DOR; +} + +unsigned short FindSPAdjustment (const char* Name) +/* Search for an entry in the table of SP adjustments */ +{ + SymEntry* Entry = FindSymInTable (SPAdjustTab, Name, HashStr (Name)); + + if (!Entry) { + Internal ("No SP adjustment label entry found"); + } + + return Entry->V.SPAdjustment; +} SymEntry* AddLabelSym (const char* Name, unsigned Flags) /* Add a goto label to the label table */ { + unsigned i; + DefOrRef *DOR, *NewDOR; + /* We juggle it so much that a shortcut will help with clarity */ + Collection *AIC = &CurrentFunc->LocalsBlockStack; + /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name)); if (Entry) { - if ((Entry->Flags & SC_DEF) != 0 && (Flags & SC_DEF) != 0) { - /* Trying to define the label more than once */ - Error ("Label `%s' is defined more than once", Name); - } - Entry->Flags |= Flags; + if (SymIsDef (Entry) && (Flags & SC_DEF) != 0) { + /* Trying to define the label more than once */ + Error ("Label '%s' is defined more than once", Name); + } + + NewDOR = AddDefOrRef (Entry, Flags); + + /* Walk through all occurrences of the label so far and evaluate + ** their relationship with the one passed to the function. + */ + for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) { + DOR = CollAt (Entry->V.L.DefsOrRefs, i); + + if ((DOR->Flags & SC_DEF) && (Flags & SC_REF) && (Flags & SC_GOTO)) { + /* We're processing a goto and here is its destination label. + ** This means the difference between SP values is already known, + ** so we simply emit the SP adjustment code. + */ + if (StackPtr != DOR->StackPtr) { + g_space (StackPtr - DOR->StackPtr); + } + + /* Are we jumping into a block with initalization of an object that + ** has automatic storage duration? Let's emit a warning. + */ + if ((long)CollLast (AIC) != DOR->LocalsBlockId && + (CollCount (AIC) < DOR->Depth || + (long)CollAt (AIC, DOR->Depth - 1) != DOR->LocalsBlockId)) { + Warning ("Goto at line %d to label %s jumps into a block with " + "initialization of an object that has automatic storage duration", + GetCurrentLine (), Name); + } + } + + + if ((DOR->Flags & SC_REF) && (DOR->Flags & SC_GOTO) && (Flags & SC_DEF)) { + /* We're processing a label, let's update all gotos encountered + ** so far + */ + SymEntry *E; + g_userodata(); + g_defdatalabel (DOR->LateSP_Label); + g_defdata (CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0); + + /* Optimizer will need the information about the value of SP adjustment + ** later, so let's preserve it. + */ + E = NewSymEntry (LocalLabelName (DOR->LateSP_Label), SC_SPADJUSTMENT); + E->V.SPAdjustment = StackPtr - DOR->StackPtr; + AddSymEntry (SPAdjustTab, E); + + /* Are we jumping into a block with initalization of an object that + ** has automatic storage duration? Let's emit a warning. + */ + if ((long)CollLast (AIC) != DOR->LocalsBlockId && + (CollCount (AIC) >= DOR->Depth || + (long)CollLast (AIC) >= (long)DOR->Line)) + Warning ("Goto at line %d to label %s jumps into a block with " + "initialization of an object that has automatic storage duration", + DOR->Line, Name); + } + + } + + Entry->Flags |= Flags; } else { - /* Create a new entry */ - Entry = NewSymEntry (Name, SC_LABEL | Flags); + /* Create a new entry */ + Entry = NewSymEntry (Name, SC_LABEL | Flags); + + /* Set a new label number */ + Entry->V.L.Label = GetLocalLabel (); + + /* Create Collection for label definition and references */ + Entry->V.L.DefsOrRefs = NewCollection (); + NewDOR = AddDefOrRef (Entry, Flags); - /* Set a new label number */ - Entry->V.Label = GetLabel (); + /* Generate the assembler name of the label */ + Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label)); - /* Add the entry to the label table */ - AddSymEntry (LabelTab, Entry); + /* Add the entry to the label table */ + AddSymEntry (LabelTab, Entry); } + /* We are processing a goto, but the label has not yet been defined */ + if (!SymIsDef (Entry) && (Flags & SC_REF) && (Flags & SC_GOTO)) { + g_lateadjustSP (NewDOR->LateSP_Label); + } + /* Return the entry */ return Entry; } -SymEntry* AddLocalSym (const char* Name, type* Type, unsigned Flags, int Offs) +SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs) /* Add a local symbol 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); + /* We have a symbol with this name already */ + Error ("Multiple definition for '%s'", Name); } else { - /* Create a new entry */ - Entry = NewSymEntry (Name, Flags); - - /* Set the symbol attributes */ - Entry->Type = TypeDup (Type); - Entry->V.Offs = Offs; - - /* Add the entry to the symbol table */ - AddSymEntry (SymTab, Entry); + /* Create a new entry */ + Entry = NewSymEntry (Name, Flags); + + /* Set the symbol attributes */ + Entry->Type = TypeDup (T); + if ((Flags & SC_AUTO) == SC_AUTO) { + Entry->V.Offs = Offs; + } else if ((Flags & SC_REGISTER) == SC_REGISTER) { + Entry->V.R.RegOffs = Offs; + Entry->V.R.SaveOffs = StackPtr; + } else if ((Flags & SC_EXTERN) == SC_EXTERN) { + Entry->V.L.Label = Offs; + SymSetAsmName (Entry); + } else if ((Flags & SC_STATIC) == SC_STATIC) { + /* Generate the assembler name from the label number */ + Entry->V.L.Label = Offs; + Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label)); + } else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) { + Entry->V.Offs = Offs; + } else { + Internal ("Invalid flags in AddLocalSym: %04X", Flags); + } + + /* Add the entry to the symbol table */ + AddSymEntry (SymTab, Entry); } @@ -661,79 +847,128 @@ SymEntry* AddLocalSym (const char* Name, type* Type, unsigned Flags, int Offs) -SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags) +SymEntry* AddGlobalSym (const char* Name, const Type* T, unsigned Flags) /* Add an external or global symbol to the symbol table and return the entry */ { + /* There is some special handling for functions, so check if it is one */ + int IsFunc = IsTypeFunc (T); + /* Functions must be inserted in the global symbol table */ - SymTable* Tab = IsTypeFunc (Type)? SymTab0 : SymTab; + SymTable* Tab = IsFunc? SymTab0 : SymTab; /* Do we have an entry with this name already? */ SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name)); if (Entry) { - - type* EType; - - /* We have a symbol with this name already */ - if (Entry->Flags & SC_TYPE) { - Error ("Multiple definition for `%s'", Name); - return Entry; - } - - /* Get the type string of the existing symbol */ - EType = Entry->Type; - - /* If we are handling arrays, the old entry or the new entry may be an - * incomplete declaration. Accept this, and if the exsting entry is - * incomplete, complete it. - */ - if (IsTypeArray (Type) && IsTypeArray (EType)) { - - /* Get the array sizes */ - unsigned Size = Decode (Type + 1); - unsigned ESize = Decode (EType + 1); - - if ((Size != 0 && ESize != 0) || - TypeCmp (Type+DECODE_SIZE+1, EType+DECODE_SIZE+1) < TC_EQUAL) { - /* Types not identical: Conflicting types */ - Error ("Conflicting types for `%s'", Name); - return Entry; - } else { - /* Check if we have a size in the existing definition */ - if (ESize == 0) { - /* Existing, size not given, use size from new def */ - Encode (EType + 1, Size); - } - } - - } else { - /* New type must be identical */ - if (TypeCmp (EType, Type) < TC_EQUAL) { - Error ("Conflicting types for `%s'", Name); - return Entry; - } - - /* In case of a function, use the new type descriptor, since it - * contains pointers to the new symbol tables that are needed if - * an actual function definition follows. - */ - if (IsTypeFunc (Type)) { - CopyEncode (Type+1, EType+1); - } - } - - /* Add the new flags */ - Entry->Flags |= Flags; + Type* EType; + + /* If the existing symbol is an enumerated constant, + ** then avoid a compiler crash. See GitHub issue #728. + */ + if (Entry->Flags & SC_ENUM) { + Fatal ("Can't redeclare enum constant '%s' as global variable", Name); + } + + /* We have a symbol with this name already */ + if (Entry->Flags & SC_TYPE) { + Error ("Multiple definition for '%s'", Name); + return Entry; + } + + /* Get the type string of the existing symbol */ + EType = Entry->Type; + + /* If we are handling arrays, the old entry or the new entry may be an + ** incomplete declaration. Accept this, and if the exsting entry is + ** incomplete, complete it. + */ + if (IsTypeArray (T) && IsTypeArray (EType)) { + + /* Get the array sizes */ + long Size = GetElementCount (T); + long ESize = GetElementCount (EType); + + if ((Size != UNSPECIFIED && ESize != UNSPECIFIED && Size != ESize) || + TypeCmp (T + 1, EType + 1) < TC_EQUAL) { + /* Types not identical: Conflicting types */ + Error ("Conflicting types for '%s'", Name); + return Entry; + } else { + /* Check if we have a size in the existing definition */ + if (ESize == UNSPECIFIED) { + /* Existing, size not given, use size from new def */ + SetElementCount (EType, Size); + } + } + + } else { + /* New type must be identical */ + if (TypeCmp (EType, T) < TC_EQUAL) { + Error ("Conflicting types for '%s'", Name); + return Entry; + } + + /* In case of a function, use the new type descriptor, since it + ** contains pointers to the new symbol tables that are needed if + ** an actual function definition follows. Be sure not to use the + ** new descriptor if it contains a function declaration with an + ** empty parameter list. + */ + if (IsFunc) { + /* Get the function descriptor from the new type */ + FuncDesc* F = GetFuncDesc (T); + /* Use this new function descriptor if it doesn't contain + ** an empty parameter list. + */ + if ((F->Flags & FD_EMPTY) == 0) { + Entry->V.F.Func = F; + SetFuncDesc (EType, F); + } + } + } + + /* If a static declaration follows a non-static declaration, then + ** warn about the conflict. (It will compile a public declaration.) + */ + if ((Flags & SC_EXTERN) == 0 && (Entry->Flags & SC_EXTERN) != 0) { + Warning ("static declaration follows non-static declaration of '%s'.", Name); + } + + /* An extern declaration must not change the current linkage. */ + if (IsFunc || (Flags & (SC_EXTERN | SC_STORAGE)) == SC_EXTERN) { + Flags &= ~SC_EXTERN; + } + + /* If a public declaration follows a static declaration, then + ** warn about the conflict. (It will compile a public declaration.) + */ + if ((Flags & SC_EXTERN) != 0 && (Entry->Flags & SC_EXTERN) == 0) { + Warning ("public declaration follows static declaration of '%s'.", Name); + } + + /* Add the new flags */ + Entry->Flags |= Flags; } else { - /* Create a new entry */ - Entry = NewSymEntry (Name, Flags); + /* Create a new entry */ + Entry = NewSymEntry (Name, Flags); + + /* Set the symbol attributes */ + Entry->Type = TypeDup (T); - /* Set the symbol attributes */ - Entry->Type = TypeDup (Type); + /* If this is a function, set the function descriptor and clear + ** additional fields. + */ + if (IsFunc) { + Entry->V.F.Func = GetFuncDesc (Entry->Type); + Entry->V.F.Seg = 0; + } - /* Add the entry to the symbol table */ - AddSymEntry (Tab, Entry); + /* Add the assembler name of the symbol */ + SymSetAsmName (Entry); + + /* Add the entry to the symbol table */ + AddSymEntry (Tab, Entry); } /* Return the entry */ @@ -743,7 +978,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags) /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ @@ -756,6 +991,14 @@ SymTable* GetSymTab (void) +SymTable* GetGlobalSymTab (void) +/* Return the global symbol table */ +{ + return SymTab0; +} + + + int SymIsLocal (SymEntry* Sym) /* Return true if the symbol is defined in the highest lexical level */ { @@ -772,9 +1015,9 @@ void MakeZPSym (const char* Name) /* Mark the symbol as zeropage */ if (Entry) { - Entry->Flags |= SC_ZEROPAGE; + Entry->Flags |= SC_ZEROPAGE; } else { - Error ("Undefined symbol: `%s'", Name); + Error ("Undefined symbol: '%s'", Name); } } @@ -796,19 +1039,19 @@ void PrintSymTable (const SymTable* Tab, FILE* F, const char* Header, ...) /* Underline the header */ while (Len--) { - fputc ('=', F); + fputc ('=', F); } fputc ('\n', F); /* Dump the table */ Entry = Tab->SymHead; if (Entry == 0) { - fprintf (F, "(empty)\n"); + fprintf (F, "(empty)\n"); } else { - while (Entry) { - DumpSymEntry (F, Entry); - Entry = Entry->NextSym; - } + while (Entry) { + DumpSymEntry (F, Entry); + Entry = Entry->NextSym; + } } fprintf (F, "\n\n\n"); } @@ -820,24 +1063,59 @@ void EmitExternals (void) { SymEntry* Entry; - AddEmptyLine (); - Entry = SymTab->SymHead; while (Entry) { - unsigned Flags = Entry->Flags; - if (Flags & SC_EXTERN) { - /* Only defined or referenced externs */ - if ((Flags & SC_REF) != 0 && (Flags & SC_DEF) == 0) { - /* An import */ - g_defimport (Entry->Name, Flags & SC_ZEROPAGE); - } else if (Flags & SC_DEF) { - /* An export */ - g_defexport (Entry->Name, Flags & SC_ZEROPAGE); - } - } - Entry = Entry->NextSym; + unsigned Flags = Entry->Flags; + if (Flags & SC_EXTERN) { + /* Only defined or referenced externs */ + if (SymIsRef (Entry) && !SymIsDef (Entry)) { + /* An import */ + g_defimport (Entry->Name, Flags & SC_ZEROPAGE); + } else if (SymIsDef (Entry)) { + /* An export */ + g_defexport (Entry->Name, Flags & SC_ZEROPAGE); + } + } + Entry = Entry->NextSym; } } +void EmitDebugInfo (void) +/* Emit debug infos for the locals of the current scope */ +{ + const char* Head; + const SymEntry* Sym; + + /* Output info for locals if enabled */ + if (DebugInfo) { + /* For cosmetic reasons in the output file, we will insert two tabs + ** on global level and just one on local level. + */ + if (LexicalLevel == LEX_LEVEL_GLOBAL) { + Head = "\t.dbg\t\tsym"; + } else { + Head = "\t.dbg\tsym"; + } + Sym = SymTab->SymHead; + while (Sym) { + if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) { + if (Sym->Flags & SC_AUTO) { + AddTextLine ("%s, \"%s\", \"00\", auto, %d", + Head, Sym->Name, Sym->V.Offs); + } else if (Sym->Flags & SC_REGISTER) { + AddTextLine ("%s, \"%s\", \"00\", register, \"regbank\", %d", + Head, Sym->Name, Sym->V.R.RegOffs); + + } else if (SymIsRef (Sym) && !SymIsDef (Sym)) { + AddTextLine ("%s, \"%s\", \"00\", %s, \"%s\"", + Head, Sym->Name, + (Sym->Flags & SC_EXTERN)? "extern" : "static", + Sym->AsmName); + } + } + Sym = Sym->NextSym; + } + } +}