]> git.sur5r.net Git - cc65/blobdiff - src/ca65/symentry.c
Remember where each symbol was defined and where it was referenced. Write this
[cc65] / src / ca65 / symentry.c
index 0603f16b575c19aef78bb42d23360a47a3232132..1b81f6a2b22d70292f11490290a74fb1c7841475 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2010, Ullrich von Bassewitz                                      */
+/* (C) 1998-2011, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -37,6 +37,7 @@
 
 /* common */
 #include "addrsize.h"
+#include "symdefs.h"
 #include "xmalloc.h"
 
 /* ca65 */
@@ -85,13 +86,15 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
     S->Right             = 0;
     S->Locals            = 0;
     S->Sym.Tab    = 0;
-    S->Pos               = CurPos;
+    S->DefLines   = EmptyCollection;
+    S->RefLines   = EmptyCollection;
     for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
         S->GuessedUse[I] = 0;
     }
     S->Flags             = Flags;
     S->DebugSymId = ~0U;
     S->ImportId   = ~0U;
+    S->ExportId   = ~0U;
     S->Expr       = 0;
     S->ExprRefs   = AUTO_COLLECTION_INITIALIZER;
     S->ExportSize = ADDR_SIZE_DEFAULT;
@@ -146,15 +149,6 @@ int SymSearchTree (SymEntry* T, const StrBuf* Name, SymEntry** E)
 
 
 
-void SymRef (SymEntry* S)
-/* Mark the given symbol as referenced */
-{
-    /* Mark the symbol as referenced */
-    S->Flags |= SF_REFERENCED;
-}
-
-
-
 void SymTransferExprRefs (SymEntry* From, SymEntry* To)
 /* Transfer all expression references from one symbol to another. */
 {
@@ -273,12 +267,16 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
      */
     if (S->Flags & SF_GLOBAL) {
         S->Flags = (S->Flags & ~SF_GLOBAL) | SF_EXPORT;
+        ReleaseFullLineInfo (&S->DefLines);
     }
 
     /* Mark the symbol as defined and use the given address size */
     S->Flags |= (SF_DEFINED | Flags);
     S->AddrSize = AddrSize;
 
+    /* Remember the line info of the symbol definition */
+    GetFullLineInfo (&S->DefLines);
+
     /* If the symbol is exported, check the address sizes */
     if (S->Flags & SF_EXPORT) {
         if (S->ExportSize == ADDR_SIZE_DEFAULT) {
@@ -286,9 +284,9 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
             S->ExportSize = S->AddrSize;
         } else if (S->AddrSize > S->ExportSize) {
             /* We're exporting a symbol smaller than it actually is */
-            PWarning (GetSymPos (S), 1, "Symbol `%m%p' is %s but exported %s",
-                      GetSymName (S), AddrSizeToStr (S->AddrSize),
-                      AddrSizeToStr (S->ExportSize));
+            Warning (1, "Symbol `%m%p' is %s but exported %s",
+                     GetSymName (S), AddrSizeToStr (S->AddrSize),
+                     AddrSizeToStr (S->ExportSize));
         }
     }
 
@@ -300,6 +298,18 @@ void SymDef (SymEntry* S, ExprNode* Expr, unsigned char AddrSize, unsigned Flags
 
 
 
+void SymRef (SymEntry* S)
+/* Mark the given symbol as referenced */
+{
+    /* Mark the symbol as referenced */
+    S->Flags |= SF_REFERENCED;
+
+    /* Remember the current location */
+    CollAppend (&S->RefLines, GetAsmLineInfo ());
+}
+
+
+
 void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
 /* Mark the given symbol as an imported symbol */
 {
@@ -342,6 +352,12 @@ void SymImport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
     /* Set the symbol data */
     S->Flags |= (SF_IMPORT | Flags);
     S->AddrSize = AddrSize;
+
+    /* Mark the position of the import as the position of the definition.
+     * Please note: In case of multiple .global or .import statements, the line
+     * infos add up.
+     */
+    GetFullLineInfo (&S->DefLines);
 }
 
 
@@ -369,6 +385,11 @@ void SymExport (SymEntry* S, unsigned char AddrSize, unsigned Flags)
             Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
         }
         S->Flags &= ~SF_GLOBAL;
+
+        /* .GLOBAL remembers line infos in case an .IMPORT follows. We have
+         * to remove these here.
+         */
+        ReleaseFullLineInfo (&S->DefLines);
     }
 
     /* If the symbol was already marked as an export, but wasn't defined
@@ -486,6 +507,11 @@ void SymGlobal (SymEntry* S, unsigned char AddrSize, unsigned Flags)
         }
         S->ExportSize = AddrSize;
         S->Flags |= (SF_GLOBAL | Flags);
+
+        /* Remember the current location as location of definition in case
+         * an .IMPORT follows later.
+         */
+        GetFullLineInfo (&S->DefLines);
     }
 }
 
@@ -552,6 +578,11 @@ void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Pri
 
     /* Set the symbol data */
     S->Flags |= (SF_EXPORT | SF_REFERENCED);
+
+    /* In case we have no line info for the definition, record it now */
+    if (CollCount (&S->DefLines) == 0) {
+        GetFullLineInfo (&S->DefLines);
+    }
 }
 
 
@@ -577,7 +608,7 @@ void SymGuessedAddrSize (SymEntry* Sym, unsigned char AddrSize)
     }
 
     /* Ok, remember the file position */
-    Sym->GuessedUse[AddrSize-1] = xdup (&CurPos, sizeof (CurPos));
+    Sym->GuessedUse[AddrSize-1] = xdup (&CurTok.Pos, sizeof (CurTok.Pos));
 }
 
 
@@ -606,7 +637,7 @@ void SymImportFromGlobal (SymEntry* S)
 
 
 
-int SymIsConst (SymEntry* S, long* Val)
+int SymIsConst (const SymEntry* S, long* Val)
 /* Return true if the given symbol has a constant value. If Val is not NULL
  * and the symbol has a constant value, store it's value there.
  */
@@ -625,6 +656,11 @@ SymTable* GetSymParentScope (SymEntry* S)
     if ((S->Flags & SF_LOCAL) != 0) {
         /* This is a cheap local symbol */
         return 0;
+    } else if (S->Sym.Tab == 0) {
+        /* Symbol not in a table. This may happen if there have been errors
+         * before. Return NULL in this case to avoid further errors.
+         */
+        return 0;
     } else {
         /* This is a global symbol */
         return S->Sym.Tab->Parent;
@@ -673,3 +709,37 @@ unsigned GetSymImportId (const SymEntry* S)
 
 
 
+unsigned GetSymExportId (const SymEntry* S)
+/* Return the export id for the given symbol */
+{
+    PRECONDITION (S != 0 && (S->Flags & SF_EXPORT) && S->ExportId != ~0U);
+    return S->ExportId;
+}
+
+
+
+unsigned GetSymInfoFlags (const SymEntry* S, long* ConstVal)
+/* Return a set of flags used when writing symbol information into a file.
+ * If the SYM_CONST bit is set, ConstVal will contain the constant value
+ * of the symbol. The result does not include the condes count.
+ * See common/symdefs.h for more information.
+ */
+{
+    /* Setup info flags */
+    unsigned Flags = 0;
+    Flags |= SymIsConst (S, ConstVal)? SYM_CONST : SYM_EXPR;
+    Flags |= (S->Flags & SF_LABEL)? SYM_LABEL : SYM_EQUATE;
+    Flags |= (S->Flags & SF_LOCAL)? SYM_CHEAP_LOCAL : SYM_STD;
+    if (S->Flags & SF_EXPORT) {
+        Flags |= SYM_EXPORT;
+    }
+    if (S->Flags & SF_IMPORT) {
+        Flags |= SYM_IMPORT;
+    }
+
+    /* Return the result */
+    return Flags;
+}
+
+
+