]> git.sur5r.net Git - cc65/blobdiff - src/cc65/symtab.c
New optimization
[cc65] / src / cc65 / symtab.c
index 6db3fc4a184be5dc46c2621ad82b62fe6d781849..3bab90d7c01bb838937a6e56f3648ce55cc500ed 100644 (file)
 #include <stdarg.h>
 #include <string.h>
 
+/* common */
+#include "check.h"
+#include "hashstr.h"
+#include "xmalloc.h"
+
+/* cc65 */
 #include "asmcode.h"
 #include "asmlabel.h"
-#include "check.h"
 #include "codegen.h"
 #include "datatype.h"
 #include "declare.h"
 #include "error.h"
 #include "funcdesc.h"
 #include "global.h"
-#include "hashstr.h"
-#include "io.h"
-#include "mem.h"
 #include "symentry.h"
+#include "typecmp.h"
 #include "symtab.h"
 
 
@@ -85,10 +88,8 @@ SymTable     EmptySymTab = {
 static unsigned                LexicalLevel    = 0;    /* For safety checks */
 static SymTable*       SymTab0         = 0;
 static SymTable*       SymTab          = 0;
-static SymTable*       StructTab0      = 0;
-static SymTable*       StructTab       = 0;
-static SymTable*       EnumTab0        = 0;
-static SymTable*       EnumTab         = 0;
+static SymTable*       TagTab0         = 0;
+static SymTable*       TagTab          = 0;
 static SymTable*       LabelTab        = 0;
 
 
@@ -164,24 +165,24 @@ static void CheckSymTable (SymTable* Tab)
            if (((Flags & SC_AUTO) || (Flags & SC_STATIC)) && (Flags & SC_EXTERN) == 0) {
                if ((Flags & SC_DEF) && !(Flags & SC_REF)) {
                    if (Flags & SC_PARAM) {
-                       Warning (WARN_UNUSED_PARM, Entry->Name);
+                       Warning ("Parameter `%s' is never used", Entry->Name);
                    } else {
-                       Warning (WARN_UNUSED_ITEM, Entry->Name);
+                       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 (ERR_UNDEFINED_LABEL, Entry->Name);
+                   Error ("Undefined label: `%s'", Entry->Name);
                } else if ((Flags & SC_REF) == 0) {
                    /* Defined but not used */
-                   Warning (WARN_UNUSED_ITEM, Entry->Name);
+                   Warning ("`%s' is defined but never used", Entry->Name);
                }
            }
-    
+
        }
 
        /* Next entry */
@@ -206,11 +207,8 @@ void EnterGlobalLevel (void)
     /* Create and assign the symbol table */
     SymTab0 = SymTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
 
-    /* Create and assign the struct table */
-    StructTab0 = StructTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
-
-    /* Create and assign the enum table */
-    EnumTab0 = EnumTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
+    /* Create and assign the tag table */
+    TagTab0 = TagTab = NewSymTable (SYMTAB_SIZE_GLOBAL);
 }
 
 
@@ -227,14 +225,12 @@ void LeaveGlobalLevel (void)
     /* Dump the tables if requested */
     if (Debug) {
        PrintSymTable (SymTab0, stdout, "Global symbol table");
-       PrintSymTable (StructTab0, stdout, "Global struct table");
-       PrintSymTable (EnumTab0, stdout, "Global enum table");
+       PrintSymTable (TagTab0, stdout, "Global tag table");
     }
 
     /* Don't delete the symbol and struct tables! */
-    SymTab0    = SymTab    = 0;
-    StructTab0 = StructTab = 0;
-    EnumTab0   = EnumTab   = 0;
+    SymTab0 = SymTab = 0;
+    TagTab0 = TagTab = 0;
 }
 
 
@@ -252,15 +248,10 @@ void EnterFunctionLevel (void)
     S->PrevTab = SymTab;
     SymTab     = S;
 
-    /* Get a new struct table and make it current */
-    S = NewSymTable (SYMTAB_SIZE_FUNCTION);
-    S->PrevTab = StructTab;
-    StructTab  = S;
-
-    /* Get a new enum table and make it current */
+    /* Get a new tag table and make it current */
     S = NewSymTable (SYMTAB_SIZE_FUNCTION);
-    S->PrevTab = EnumTab;
-    EnumTab    = S;
+    S->PrevTab = TagTab;
+    TagTab  = S;
 
     /* Create and assign a new label table */
     LabelTab = NewSymTable (SYMTAB_SIZE_LABEL);
@@ -275,14 +266,12 @@ void RememberFunctionLevel (struct FuncDesc* F)
     --LexicalLevel;
 
     /* Remember the tables */
-    F->SymTab   = SymTab;
-    F->StructTab = StructTab;
-    F->EnumTab  = EnumTab;
+    F->SymTab = SymTab;
+    F->TagTab = TagTab;
 
     /* Don't delete the tables */
-    SymTab    = SymTab->PrevTab;
-    StructTab = StructTab->PrevTab;
-    EnumTab   = EnumTab->PrevTab;
+    SymTab = SymTab->PrevTab;
+    TagTab = TagTab->PrevTab;
 }
 
 
@@ -297,11 +286,8 @@ void ReenterFunctionLevel (struct FuncDesc* F)
     F->SymTab->PrevTab = SymTab;
     SymTab = F->SymTab;
 
-    F->StructTab->PrevTab = StructTab;
-    StructTab = F->StructTab;
-
-    F->EnumTab->PrevTab = EnumTab;
-    EnumTab = F->EnumTab;
+    F->TagTab->PrevTab = TagTab;
+    TagTab = F->TagTab;
 
     /* Create and assign a new label table */
     LabelTab = NewSymTable (SYMTAB_SIZE_LABEL);
@@ -325,9 +311,8 @@ void LeaveFunctionLevel (void)
     }
 
     /* Don't delete the tables */
-    SymTab    = SymTab->PrevTab;
-    StructTab = StructTab->PrevTab;
-    EnumTab   = EnumTab->PrevTab;
+    SymTab = SymTab->PrevTab;
+    TagTab = TagTab->PrevTab;
     LabelTab  = 0;
 }
 
@@ -346,15 +331,10 @@ void EnterBlockLevel (void)
     S->PrevTab         = SymTab;
     SymTab             = S;
 
-    /* Get a new struct table and make it current */
-    S = NewSymTable (SYMTAB_SIZE_BLOCK);
-    S->PrevTab         = StructTab;
-    StructTab   = S;
-
-    /* Get a new enum table and make it current */
+    /* Get a new tag table and make it current */
     S = NewSymTable (SYMTAB_SIZE_BLOCK);
-    S->PrevTab = EnumTab;
-    EnumTab    = S;
+    S->PrevTab = TagTab;
+    TagTab     = S;
 }
 
 
@@ -369,9 +349,8 @@ void LeaveBlockLevel (void)
     CheckSymTable (SymTab);
 
     /* Don't delete the tables */
-    SymTab    = SymTab->PrevTab;
-    StructTab = StructTab->PrevTab;
-    EnumTab   = EnumTab->PrevTab;
+    SymTab = SymTab->PrevTab;
+    TagTab = TagTab->PrevTab;
 }
 
 
@@ -462,18 +441,18 @@ SymEntry* FindSym (const char* Name)
 
 
 
-SymEntry* FindStructSym (const char* Name)
-/* Find the symbol with the given name in the struct table */
+SymEntry* FindLocalSym (const char* Name)
+/* Find the symbol with the given name in the current symbol table only */
 {
-    return FindSymInTree (StructTab, Name);
+    return FindSymInTable (SymTab, Name, HashStr (Name));
 }
 
 
 
-SymEntry* FindEnumSym (const char* Name)
-/* Find the symbol with the given name in the enum table */
+SymEntry* FindTagSym (const char* Name)
+/* Find the symbol with the given name in the tag table */
 {
-    return FindSymInTree (EnumTab, Name);
+    return FindSymInTree (TagTab, Name);
 }
 
 
@@ -489,7 +468,7 @@ SymEntry* FindStructField (const type* Type, const char* Name)
     }
 
     /* Non-structs do not have any struct fields... */
-    if (IsStruct (Type)) {
+    if (IsClassStruct (Type)) {
 
        const SymTable* Tab;
 
@@ -551,16 +530,16 @@ SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab)
 /* Add a struct/union entry and return it */
 {
     /* Do we have an entry with this name already? */
-    SymEntry* Entry = FindSymInTable (StructTab, Name, HashStr (Name));
+    SymEntry* 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) {
+       if ((Entry->Flags & SC_STRUCT) == 0) {
            /* Existing symbol is not a struct */
-           Error (ERR_SYMBOL_KIND);
+           Error ("Symbol `%s' is already different kind", Name);
        } else if (Size > 0 && Entry->V.S.Size > 0) {
            /* Both structs are definitions. */
-           Error (ERR_MULTIPLE_DEFINITION, Name);
+           Error ("Multiple definition for `%s'", Name);
        } else {
            /* Define the struct size if it is given */
            if (Size > 0) {
@@ -579,7 +558,7 @@ SymEntry* AddStructSym (const char* Name, unsigned Size, SymTable* Tab)
        Entry->V.S.Size   = Size;
 
        /* Add it to the current table */
-       AddSymEntry (StructTab, Entry);
+       AddSymEntry (TagTab, Entry);
     }
 
     /* Return the entry */
@@ -595,9 +574,9 @@ SymEntry* AddEnumSym (const char* Name, int Val)
     SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
     if (Entry) {
        if (Entry->Flags != SC_ENUM) {
-           Error (ERR_SYMBOL_KIND);
+           Error ("Symbol `%s' is already different kind", Name);
        } else {
-           Error (ERR_MULTIPLE_DEFINITION, Name);
+           Error ("Multiple definition for `%s'", Name);
        }
        return Entry;
     }
@@ -629,7 +608,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
 
        if ((Entry->Flags & SC_DEF) != 0 && (Flags & SC_DEF) != 0) {
            /* Trying to define the label more than once */
-                   Error (ERR_MULTIPLE_DEFINITION, Name);
+                   Error ("Label `%s' is defined more than once", Name);
        }
        Entry->Flags |= Flags;
 
@@ -655,22 +634,12 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
 SymEntry* AddLocalSym (const char* Name, type* Type, unsigned Flags, int Offs)
 /* Add a local symbol and return the symbol entry */
 {
-    SymEntry* Entry;
-
-    /* Functions declared inside of functions do always have external linkage */
-    if (Type != 0 && IsFunc (Type)) {
-               if ((Flags & (SC_DEFAULT | SC_EXTERN)) == 0) {
-                   Warning (WARN_FUNC_MUST_BE_EXTERN);
-               }
-               Flags = SC_EXTERN;
-    }
-
     /* Do we have an entry with this name already? */
-    Entry = FindSymInTable (SymTab, Name, HashStr (Name));
+    SymEntry* Entry = FindSymInTable (SymTab, Name, HashStr (Name));
     if (Entry) {
 
        /* We have a symbol with this name already */
-       Error (ERR_MULTIPLE_DEFINITION, Name);
+       Error ("Multiple definition for `%s'", Name);
 
     } else {
 
@@ -696,7 +665,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
 /* Add an external or global symbol to the symbol table and return the entry */
 {
     /* Functions must be inserted in the global symbol table */
-    SymTable* Tab = IsFunc (Type)? SymTab0 : SymTab;
+    SymTable* Tab = IsTypeFunc (Type)? SymTab0 : SymTab;
 
     /* Do we have an entry with this name already? */
     SymEntry* Entry = FindSymInTable (Tab, Name, HashStr (Name));
@@ -706,7 +675,7 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
 
        /* We have a symbol with this name already */
        if (Entry->Flags & SC_TYPE) {
-           Error (ERR_MULTIPLE_DEFINITION, Name);
+           Error ("Multiple definition for `%s'", Name);
            return Entry;
        }
 
@@ -717,16 +686,17 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
         * incomplete declaration. Accept this, and if the exsting entry is
         * incomplete, complete it.
         */
-       if (IsArray (Type) && IsArray (EType)) {
+       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) != 0) {
-               /* Types not identical: Duplicate definition */
-               Error (ERR_MULTIPLE_DEFINITION, Name);
+               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) {
@@ -737,16 +707,17 @@ SymEntry* AddGlobalSym (const char* Name, type* Type, unsigned Flags)
 
                } else {
            /* New type must be identical */
-           if (!EqualTypes (EType, Type) != 0) {
-               Error (ERR_MULTIPLE_DEFINITION, Name);
+           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 (IsFunc (Type)) {
-               CopyEncode (Type+1, EType+1);
+           if (IsTypeFunc (Type)) {
+               CopyEncode (Type+1, EType+1);
            }
        }
 
@@ -785,128 +756,10 @@ SymTable* GetSymTab (void)
 
 
 
-static int EqualSymTables (SymTable* Tab1, SymTable* Tab2)
-/* Compare two symbol tables. Return 1 if they are equal and 0 otherwise */
+int SymIsLocal (SymEntry* Sym)
+/* Return true if the symbol is defined in the highest lexical level */
 {
-    /* Compare the parameter lists */
-    SymEntry* Sym1 = Tab1->SymHead;
-    SymEntry* Sym2 = Tab2->SymHead;
-
-    /* Compare the fields */
-    while (Sym1 && Sym2) {
-
-       /* Compare this field */
-       if (!EqualTypes (Sym1->Type, Sym2->Type)) {
-           /* Field types not equal */
-           return 0;
-       }
-
-       /* Get the pointers to the next fields */
-       Sym1 = Sym1->NextSym;
-       Sym2 = Sym2->NextSym;
-    }
-
-    /* Check both pointers against NULL to compare the field count */
-    return (Sym1 == 0 && Sym2 == 0);
-}
-
-
-
-int EqualTypes (const type* Type1, const type* Type2)
-/* Recursively compare two types. Return 1 if the types match, return 0
- * otherwise.
- */
-{
-    int v1, v2;
-    SymEntry* Sym1;
-    SymEntry* Sym2;
-    SymTable* Tab1;
-    SymTable* Tab2;
-    FuncDesc* F1;
-    FuncDesc* F2;
-
-
-    /* Shortcut here: If the pointers are identical, the types are identical */
-    if (Type1 == Type2) {
-       return 1;
-    }
-
-    /* Compare two types. Determine, where they differ */
-    while (*Type1 == *Type2 && *Type1 != T_END) {
-
-       switch (*Type1) {
-
-           case T_FUNC:
-               /* Compare the function descriptors */
-               F1 = DecodePtr (Type1+1);
-               F2 = DecodePtr (Type2+1);
-               if ((F1->Flags & ~FD_IMPLICIT) != (F2->Flags & ~FD_IMPLICIT)) {
-                   /* Flags differ */
-                   return 0;
-               }
-
-               /* Compare the parameter lists */
-               if (EqualSymTables (F1->SymTab, F2->SymTab)       == 0 ||
-                   EqualSymTables (F1->StructTab, F2->StructTab) == 0 ||
-                   EqualSymTables (F1->EnumTab, F2->EnumTab) == 0) {
-                   /* One of the tables is not identical */
-                   return 0;
-               }
-
-               /* Skip the FuncDesc pointers to compare the return type */
-               Type1 += DECODE_SIZE;
-               Type2 += DECODE_SIZE;
-               break;
-
-           case T_ARRAY:
-               /* Check member count */
-               v1 = Decode (Type1+1);
-               v2 = Decode (Type2+1);
-               if (v1 != 0 && v2 != 0 && v1 != v2) {
-                   /* Member count given but different */
-                   return 0;
-               }
-               Type1 += DECODE_SIZE;
-               Type2 += DECODE_SIZE;
-               break;
-
-           case T_STRUCT:
-           case T_UNION:
-                       /* Compare the fields recursively. To do that, we fetch the
-                * pointer to the struct definition from the type, and compare
-                * the fields.
-                */
-               Sym1 = DecodePtr (Type1+1);
-               Sym2 = DecodePtr (Type2+1);
-
-               /* Get the field tables from the struct entry */
-               Tab1 = Sym1->V.S.SymTab;
-               Tab2 = Sym2->V.S.SymTab;
-
-               /* One or both structs may be forward definitions. In this case,
-                * the symbol tables are both non existant. Assume that the
-                * structs are equal in this case.
-                */
-               if (Tab1 != 0 && Tab2 != 0) {
-
-                   if (EqualSymTables (Tab1, Tab2) == 0) {
-                       /* Field lists are not equal */
-                       return 0;
-                   }
-
-               }
-
-               /* Structs are equal */
-               Type1 += DECODE_SIZE;
-               Type2 += DECODE_SIZE;
-               break;
-       }
-       ++Type1;
-               ++Type2;
-    }
-
-    /* Done, types are equal */
-    return 1;
+    return (Sym->Owner == SymTab || Sym->Owner == TagTab);
 }
 
 
@@ -921,7 +774,7 @@ void MakeZPSym (const char* Name)
     if (Entry) {
        Entry->Flags |= SC_ZEROPAGE;
     } else {
-       Error (ERR_UNDEFINED_SYMBOL, Name);
+       Error ("Undefined symbol: `%s'", Name);
     }
 }