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 */
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 */
};
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;
- }
}
}
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;
}
-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 */
+ }
}
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);
}
* 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);
- }
- }
}
/* 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.
if (LI == 0) {
/* Allocate a new LineInfo */
LI = NewLineInfo (&Key);
- } else {
- Key.Count = 2;
}
/* Open the spans for this line info */
-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) {
/* 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);
+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 */
{
/* Get a pointer to the line info */
const LineInfo* LI = CollConstAt (LineInfos, I);
+ /* Safety */
CHECK (LI->Id != ~0U);
/* Write the index to the file */
{
unsigned I;
+ Collection EmptySpans = STATIC_COLLECTION_INITIALIZER;
+
/* Tell the object file module that we're about to write line infos */
ObjStartLineInfos ();
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);
}