/*****************************************************************************/
/* */
-/* lineinfo.c */
+/* lineinfo.c */
/* */
-/* Source file line info structure */
+/* Source file line info structure */
/* */
/* */
/* */
+#include <stdio.h>
#include <string.h>
/* common */
#include "xmalloc.h"
/* ca65 */
+#include "filetab.h"
#include "global.h"
#include "lineinfo.h"
#include "objfile.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
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* K = Key;
/* Hash over a combination of type, file and line */
- return HashInt ((K->Type << 18) ^ (K->Pos.Name << 14) ^ K->Pos.Line);
+ return HashInt ((K->Type << 21) ^ (K->Pos.Name << 14) ^ K->Pos.Line);
}
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_Insert (&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 */
+ }
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
+#if 0
+static void DumpLineInfos (const char* Title, const Collection* C)
+/* Dump line infos from the given collection */
+{
+ unsigned I;
+ fprintf (stderr, "%s:\n", Title);
+ for (I = 0; I < CollCount (C); ++I) {
+ const LineInfo* LI = CollConstAt (C, I);
+ const char* Type;
+ switch (GetLineInfoType (LI)) {
+ case LI_TYPE_ASM: Type = "ASM"; break;
+ case LI_TYPE_EXT: Type = "EXT"; break;
+ case LI_TYPE_MACRO: Type = "MACRO"; break;
+ case LI_TYPE_MACPARAM: Type = "MACPARAM"; break;
+ default: Type = "unknown"; break;
+ }
+ fprintf (stderr,
+ "%2u: %-8s %2u %-16s %u/%u\n",
+ I, Type, LI->Key.Pos.Name,
+ SB_GetConstBuf (GetFileName (LI->Key.Pos.Name)),
+ LI->Key.Pos.Line, LI->Key.Pos.Col);
+ }
+}
+#endif
+
+
+
void InitLineInfo (void)
/* Initialize the line infos */
{
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);
}
void EndLine (LineInfo* LI)
/* End a line that is tracked by the given LineInfo structure */
{
- unsigned I;
-
/* Close the spans for the line */
- CloseSpans (&LI->OpenSpans);
+ CloseSpanList (&LI->OpenSpans);
/* Move the spans to the list of all spans for this line, then clear the
* list of open spans.
*/
- for (I = 0; I < CollCount (&LI->OpenSpans); ++I) {
- CollAppend (&LI->Spans, CollAtUnchecked (&LI->OpenSpans, I));
- }
+ CollTransfer (&LI->Spans, &LI->OpenSpans);
CollDeleteAll (&LI->OpenSpans);
/* Line info is no longer active - remove it from the list of current
* 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.
*/
- LI = HT_FindEntry (&LineInfoTab, &Key);
+ LI = HT_Find (&LineInfoTab, &Key);
if (LI == 0) {
/* Allocate a new LineInfo */
LI = NewLineInfo (&Key);
- } else {
- Key.Count = 2;
}
/* Open the spans for this line info */
- OpenSpans (&LI->OpenSpans);
+ OpenSpanList (&LI->OpenSpans);
/* Add the line info to the list of current line infos */
CollAppend (&CurLineInfo, LI);
-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);
+ /* Bum the reference counter for all active line infos */
+ for (I = 0; I < CollCount (&CurLineInfo); ++I) {
+ ++((LineInfo*)CollAt (&CurLineInfo, I))->RefCount;
+ }
- /* Grow the collection as necessary */
- CollGrow (LineInfos, CollCount (&CurLineInfo));
+ /* Copy all line infos over */
+ CollTransfer (LineInfos, &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;
- }
+void ReleaseFullLineInfo (Collection* LineInfos)
+/* Decrease the reference count for a collection full of LineInfos, then clear
+ * the collection.
+ */
+{
+ unsigned I;
- /* Return it to the caller */
- CollAppend (LineInfos, LI);
+ /* 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);
}
/* Get a pointer to the line info */
const LineInfo* LI = CollConstAt (LineInfos, I);
+ /* Safety */
CHECK (LI->Id != ~0U);
/* Write the index to the file */
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);
+ /* Write the ids of the spans for this line */
+ WriteSpanList (&LI->Spans);
}
/* End of line infos */