]> git.sur5r.net Git - cc65/blobdiff - src/ca65/lineinfo.c
Remember where each symbol was defined and where it was referenced. Write this
[cc65] / src / ca65 / lineinfo.c
index 7c8bf68fe698ba5ff8a499f971b78a2584cc61ae..cddd17ac3c0a652b92318a85ed83561cadf3dd14 100644 (file)
@@ -79,8 +79,7 @@ static int HT_Compare (const void* Key1, const void* Key2);
 typedef struct LineInfoKey LineInfoKey;
 struct LineInfoKey {
     FilePos         Pos;                /* File position */
-    unsigned short  Type;               /* Type of line info */
-    unsigned short  Count;              /* Recursion counter */
+    unsigned        Type;               /* Type/count of line info */
 };
 
 /* Structure that holds line info */
@@ -88,8 +87,7 @@ struct LineInfo {
     HashNode        Node;               /* Hash table node */
     unsigned        Id;                 /* Index */
     LineInfoKey     Key;                /* Key for this line info */
-    unsigned char   Hashed;             /* True if in hash list */
-    unsigned char   Referenced;         /* Force reference even if no spans */
+    unsigned        RefCount;           /* Reference counter */
     Collection      Spans;              /* Segment spans for this line info */
     Collection      OpenSpans;          /* List of currently open spans */
 };
@@ -153,15 +151,12 @@ static int HT_Compare (const void* Key1, const void* Key2)
     const LineInfoKey* K1 = Key1;
     const LineInfoKey* K2 = Key2;
 
-    /* Compare line number, then file and type, then count */
+    /* Compare line number, then file and type */
     int Res = (int)K2->Pos.Line - (int)K1->Pos.Line;
     if (Res == 0) {
         Res = (int)K2->Pos.Name - (int)K1->Pos.Name;
         if (Res == 0) {
             Res = (int)K2->Type - (int)K1->Type;
-            if (Res == 0) {
-                Res = (int)K2->Count - (int)K1->Count;
-            }
         }
     }
 
@@ -187,11 +182,13 @@ static LineInfo* NewLineInfo (const LineInfoKey* Key)
     InitHashNode (&LI->Node);
     LI->Id        = ~0U;
     LI->Key       = *Key;
-    LI->Hashed    = 0;
-    LI->Referenced= 0;
+    LI->RefCount  = 0;
     InitCollection (&LI->Spans);
     InitCollection (&LI->OpenSpans);
 
+    /* Add it to the hash table, so we will find it if necessary */
+    HT_InsertEntry (&LineInfoTab, LI);
+
     /* Return the new struct */
     return LI;
 }
@@ -212,22 +209,21 @@ static void FreeLineInfo (LineInfo* LI)
 
 
 
-static void RememberLineInfo (LineInfo* LI)
-/* Remember a LineInfo by adding it to the hash table and the global list.
- * This will also assign the id which is actually the list position.
- */
+static int CheckLineInfo (void* Entry, void* Data attribute ((unused)))
+/* Called from HT_Walk. Remembers used line infos and assigns them an id */
 {
-    /* Assign the id */
-    LI->Id = CollCount (&LineInfoList);
-
-    /* Remember it in the global list */
-    CollAppend (&LineInfoList, LI);
-
-    /* Add it to the hash table, so we will find it if necessary */
-    HT_InsertEntry (&LineInfoTab, LI);
-
-    /* Remember that we have it */
-    LI->Hashed = 1;
+    /* Entry is actually a line info */
+    LineInfo* LI = Entry;
+
+    /* The entry is used if there are spans or the ref counter is non zero */
+    if (LI->RefCount > 0 || CollCount (&LI->Spans) > 0) {
+        LI->Id = CollCount (&LineInfoList);
+        CollAppend (&LineInfoList, LI);
+        return 0;       /* Keep the entry */
+    } else {
+        FreeLineInfo (LI);
+        return 1;       /* Remove entry from table */
+    }
 }
 
 
@@ -262,6 +258,12 @@ void DoneLineInfo (void)
     while (Count) {
         EndLine (CollAt (&CurLineInfo, --Count));
     }
+
+    /* Walk over the entries in the hash table and sort them into used and
+     * unused ones. Add the used ones to the line info list and assign them
+     * an id.
+     */
+    HT_Walk (&LineInfoTab, CheckLineInfo, 0);
 }
 
 
@@ -286,18 +288,6 @@ void EndLine (LineInfo* LI)
      * line infos.
      */
     CollDeleteItem (&CurLineInfo, LI);
-
-    /* If this line info is already hashed, we're done. Otherwise, if it is
-     * marked as referenced or has non empty spans, remember it. It it is not
-     * referenced or doesn't have open spans, delete it.
-     */
-    if (!LI->Hashed) {
-        if (LI->Referenced || CollCount (&LI->Spans) > 0) {
-            RememberLineInfo (LI);
-        } else {
-            FreeLineInfo (LI);
-        }
-    }
 }
 
 
@@ -310,8 +300,7 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count)
 
     /* Prepare the key struct */
     Key.Pos   = *Pos;
-    Key.Type  = Type;
-    Key.Count = Count;
+    Key.Type  = LI_MAKE_TYPE (Type, Count);
 
     /* Try to find a line info with this position and type in the hash table.
      * If so, reuse it. Otherwise create a new one.
@@ -320,8 +309,6 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count)
     if (LI == 0) {
         /* Allocate a new LineInfo */
         LI = NewLineInfo (&Key);
-    } else {
-        Key.Count = 2;
     }
 
     /* Open the spans for this line info */
@@ -360,21 +347,39 @@ void NewAsmLine (void)
 
 
 
-void GetFullLineInfo (Collection* LineInfos, int ForceRef)
+LineInfo* GetAsmLineInfo (void)
+/* Return the line info for the current assembler file. The function will
+ * bump the reference counter before returning the line info.
+ */
+{
+    ++AsmLineInfo->RefCount;
+    return AsmLineInfo;
+}
+
+
+
+void ReleaseLineInfo (LineInfo* LI)
+/* Decrease the reference count for a line info */
+{
+    /* Decrease the reference counter */
+    CHECK (LI->RefCount > 0);
+    ++LI->RefCount;
+}
+
+
+
+void GetFullLineInfo (Collection* LineInfos)
 /* Return full line infos, that is line infos for currently active Slots. The
- * function will clear LineInfos before usage. If ForceRef is not zero, a
- * forced reference will be added to all line infos, with the consequence that
- * they won't get deleted, even if there is no code or data generated for these
- * lines.
+ * infos will be added to the given collection, existing entries will be left
+ * intact. The reference count of all added entries will be increased.
  */
 {
     unsigned I;
 
-    /* Clear the collection */
-    CollDeleteAll (LineInfos);
-
-    /* Grow the collection as necessary */
-    CollGrow (LineInfos, CollCount (&CurLineInfo));
+    /* If the collection is currently empty, grow it as necessary */
+    if (CollCount (LineInfos) == 0) {
+        CollGrow (LineInfos, CollCount (&CurLineInfo));
+    }
 
     /* Copy all valid line infos to the collection */
     for (I = 0; I < CollCount (&CurLineInfo); ++I) {
@@ -382,10 +387,8 @@ void GetFullLineInfo (Collection* LineInfos, int ForceRef)
         /* Get the line info from the slot */
         LineInfo* LI = CollAt (&CurLineInfo, I);
 
-        /* Mark it as referenced */
-        if (ForceRef) {
-            LI->Referenced = 1;
-        }
+        /* Bump the reference counter */
+        ++LI->RefCount;
 
         /* Return it to the caller */
         CollAppend (LineInfos, LI);
@@ -394,6 +397,25 @@ void GetFullLineInfo (Collection* LineInfos, int ForceRef)
 
 
 
+void ReleaseFullLineInfo (Collection* LineInfos)
+/* Decrease the reference count for a collection full of LineInfos, then clear
+ * the collection.
+ */
+{
+    unsigned I;
+
+    /* Walk over all entries */
+    for (I = 0; I < CollCount (LineInfos); ++I) {
+        /* Release the the line info */
+        ReleaseLineInfo (CollAt (LineInfos, I));
+    }
+
+    /* Delete all entries */
+    CollDeleteAll (LineInfos);
+}
+
+
+
 const FilePos* GetSourcePos (const LineInfo* LI)
 /* Return the source file position from the given line info */
 {
@@ -424,6 +446,7 @@ void WriteLineInfo (const Collection* LineInfos)
         /* Get a pointer to the line info */
         const LineInfo* LI = CollConstAt (LineInfos, I);
 
+        /* Safety */
         CHECK (LI->Id != ~0U);
 
         /* Write the index to the file */
@@ -438,6 +461,8 @@ void WriteLineInfos (void)
 {
     unsigned I;
 
+    Collection EmptySpans = STATIC_COLLECTION_INITIALIZER;
+
     /* Tell the object file module that we're about to write line infos */
     ObjStartLineInfos ();
 
@@ -454,14 +479,24 @@ void WriteLineInfos (void)
         ObjWritePos (&LI->Key.Pos);
 
         /* Write the type and count of the line info */
-        ObjWriteVar (LI_MAKE_TYPE (LI->Key.Type, LI->Key.Count));
+        ObjWriteVar (LI->Key.Type);
 
-        /* Write the spans for this line */
-        WriteSpans (&LI->Spans);
+        /* Spans are only added to the debug file if debug information is
+         * requested. Otherwise we write an empty list.
+         */
+        if (DbgSyms) {
+            WriteSpans (&LI->Spans);
+        } else {
+            /* Write out an empty list */
+            WriteSpans (&EmptySpans);
+        }
     }
 
     /* End of line infos */
     ObjEndLineInfos ();
+
+    /* For the sake of completeness, but not really necessary */
+    DoneCollection (&EmptySpans);
 }