]> git.sur5r.net Git - cc65/commitdiff
Complete redesign of line info generation. Uses spans instead of a fragment
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 14 Aug 2011 19:23:16 +0000 (19:23 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 14 Aug 2011 19:23:16 +0000 (19:23 +0000)
list as before.

git-svn-id: svn://svn.cc65.org/cc65/trunk@5162 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/condasm.c
src/ca65/dbginfo.c
src/ca65/filetab.c
src/ca65/lineinfo.c
src/ca65/lineinfo.h
src/ca65/macro.c
src/ca65/main.c
src/ca65/scanner.c
src/ca65/span.c
src/ca65/toklist.c
src/ca65/toklist.h

index fc0e0ba773e0038a3850eaa1e953c47a787abbd8..274b1a1d9451af770eba134c27e4c377a5ce5374 100644 (file)
@@ -487,7 +487,7 @@ void CheckOpenIfs (void)
        }
 
         LI = CollConstAt (&D->LineInfos, 0);
-       if (LI->Pos.Name != CurTok.Pos.Name) {
+               if (GetSourcePos (LI)->Name != CurTok.Pos.Name) {
            /* The .if is from another file, bail out */
            break;
        }
index 59390cc62ecc1a3f4f9aa6c9d6ed2c396c3a1820..86a470d6c80577aaf541741a18edb336573318ab 100644 (file)
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                          Data                                    */
+/*****************************************************************************/
+
+
+
+/* The current line info */
+static LineInfo* CurLineInfo = 0;
+
+
+
+/*****************************************************************************/
+/*                                   Code                                    */
 /*****************************************************************************/
 
 
@@ -99,11 +110,16 @@ void DbgInfoLine (void)
     long Line;
     FilePos Pos = STATIC_FILEPOS_INITIALIZER;
 
+    /* Any new line info terminates the last one */
+    if (CurLineInfo) {
+        EndLine (CurLineInfo);
+        CurLineInfo = 0;
+    }
+
     /* If a parameters follow, this is actual line info. If no parameters
      * follow, the last line info is terminated.
      */
     if (CurTok.Tok == TOK_SEP) {
-       ClearLineInfo (LI_SLOT_EXT);
        return;
     }
 
@@ -133,8 +149,8 @@ void DbgInfoLine (void)
     }
     Pos.Line = Line;
 
-    /* Remember the line info */
-    GenLineInfo (LI_SLOT_EXT, &Pos);
+    /* Generate a new external line info */
+    CurLineInfo = StartLine (&Pos, LI_TYPE_EXT, 0);
 }
 
 
index ad760988f09c94eb7bab40137a160306659d4c0d..84282296bbfa9e2eacaf77caf3319c374dacd568 100644 (file)
@@ -61,7 +61,7 @@
 static unsigned HT_GenHash (const void* Key);
 /* Generate the hash over a key. */
 
-static const void* HT_GetKey (void* Entry);
+static const void* HT_GetKey (const void* Entry);
 /* Given a pointer to the user entry data, return a pointer to the key. */
 
 static int HT_Compare (const void* Key1, const void* Key2);
@@ -122,7 +122,7 @@ static unsigned HT_GenHash (const void* Key)
 
 
 
-static const void* HT_GetKey (void* Entry)
+static const void* HT_GetKey (const void* Entry)
 /* Given a pointer to the user entry data, return a pointer to the index */
 {
     return &((FileEntry*) Entry)->Name;
@@ -134,7 +134,7 @@ static int HT_Compare (const void* Key1, const void* Key2)
 /* Compare two keys. The function must return a value less than zero if
  * Key1 is smaller than Key2, zero if both are equal, and a value greater
  * than zero if Key1 is greater then Key2.
- */
+ */                                 
 {
     return (int)*(const unsigned*)Key1 - (int)*(const unsigned*)Key2;
 }
index d1faa21a26133ceee40b9957ed2e0d5a94f8e8c5..7c8bf68fe698ba5ff8a499f971b78a2584cc61ae 100644 (file)
 
 
 #include <string.h>
-#include <limits.h>
 
 /* common */
 #include "coll.h"
+#include "hashfunc.h"
 #include "xmalloc.h"
 
 /* ca65 */
 #include "global.h"
 #include "lineinfo.h"
 #include "objfile.h"
+#include "scanner.h"
+#include "span.h"
+
+
+
+/*****************************************************************************/
+/*                                 Forwards                                  */
+/*****************************************************************************/
+
+
+
+static unsigned HT_GenHash (const void* Key);
+/* Generate the hash over a key. */
+
+static const void* HT_GetKey (const void* Entry);
+/* Given a pointer to the user entry data, return a pointer to the key */
+
+static int HT_Compare (const void* Key1, const void* Key2);
+/* Compare two keys. The function must return a value less than zero if
+ * Key1 is smaller than Key2, zero if both are equal, and a value greater
+ * than zero if Key1 is greater then Key2.
+ */
 
 
 
 
 
 
-/* An invalid line info index */
-#define INV_LINEINFO_INDEX      UINT_MAX
+/* Structure that holds the key for a line info */
+typedef struct LineInfoKey LineInfoKey;
+struct LineInfoKey {
+    FilePos         Pos;                /* File position */
+    unsigned short  Type;               /* Type of line info */
+    unsigned short  Count;              /* Recursion counter */
+};
+
+/* Structure that holds line info */
+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 */
+    Collection      Spans;              /* Segment spans for this line info */
+    Collection      OpenSpans;          /* List of currently open spans */
+};
+
+
 
 /* Collection containing all line infos */
-static Collection LineInfoColl = STATIC_COLLECTION_INITIALIZER;
+static Collection LineInfoList = STATIC_COLLECTION_INITIALIZER;
 
-/* Number of valid (=used) line infos in LineInfoColl */
-static unsigned UsedLineInfoCount;
+/* Collection with currently active line infos */
+static Collection CurLineInfo = STATIC_COLLECTION_INITIALIZER;
 
-/* Entry in CurLineInfo */
-typedef struct LineInfoSlot LineInfoSlot;
-struct LineInfoSlot {
-    unsigned    Type;
-    LineInfo*   Info;
+/* Hash table functions */
+static const HashFunctions HashFunc = {
+    HT_GenHash,
+    HT_GetKey,
+    HT_Compare
 };
 
-/* Dynamically allocated array of LineInfoSlots */
-static LineInfoSlot* CurLineInfo;
-static unsigned AllocatedSlots;
-static unsigned UsedSlots;
+/* Line info hash table */
+static HashTable LineInfoTab = STATIC_HASHTABLE_INITIALIZER (1051, &HashFunc);
+
+/* The current assembler input line */
+static LineInfo* AsmLineInfo = 0;
+
+
+
+/*****************************************************************************/
+/*                           Hash table functions                            */
+/*****************************************************************************/
+
+
+
+static unsigned HT_GenHash (const void* Key)
+/* Generate the hash over a key. */
+{
+    /* Key is a LineInfoKey pointer */
+    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);
+}
+
+
+
+static const void* HT_GetKey (const void* Entry)
+/* Given a pointer to the user entry data, return a pointer to the key */
+{
+    return &((const LineInfo*)Entry)->Key;
+}
+
+
+
+static int HT_Compare (const void* Key1, const void* Key2)
+/* Compare two keys. The function must return a value less than zero if
+ * Key1 is smaller than Key2, zero if both are equal, and a value greater
+ * than zero if Key1 is greater then Key2.
+ */
+{
+    /* Convert both parameters to FileInfoKey pointers */
+    const LineInfoKey* K1 = Key1;
+    const LineInfoKey* K2 = Key2;
+
+    /* Compare line number, then file and type, then count */
+    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;
+            }
+        }
+    }
+
+    /* Done */
+    return Res;
+}
 
 
 
@@ -82,20 +177,20 @@ static unsigned UsedSlots;
 
 
 
-static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos)
+static LineInfo* NewLineInfo (const LineInfoKey* Key)
 /* Create and return a new line info. Usage will be zero. */
 {
     /* Allocate memory */
     LineInfo* LI = xmalloc (sizeof (LineInfo));
 
     /* Initialize the fields */
-    LI->Usage   = 0;
-    LI->Type    = Type;
-    LI->Index   = INV_LINEINFO_INDEX;
-    LI->Pos     = *Pos;
-
-    /* Add the line info to the list of all line infos */
-    CollAppend (&LineInfoColl, LI);
+    InitHashNode (&LI->Node);
+    LI->Id        = ~0U;
+    LI->Key       = *Key;
+    LI->Hashed    = 0;
+    LI->Referenced= 0;
+    InitCollection (&LI->Spans);
+    InitCollection (&LI->OpenSpans);
 
     /* Return the new struct */
     return LI;
@@ -103,6 +198,40 @@ static LineInfo* NewLineInfo (unsigned Type, const FilePos* Pos)
 
 
 
+static void FreeLineInfo (LineInfo* LI)
+/* Free a LineInfo structure */
+{
+    /* Free the Spans collection. It is supposed to be empty */
+    CHECK (CollCount (&LI->Spans) == 0);
+    DoneCollection (&LI->Spans);
+    DoneCollection (&LI->OpenSpans);
+
+    /* Free the structure itself */
+    xfree (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.
+ */
+{
+    /* 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;
+}
+
+
+
 /*****************************************************************************/
 /*                                          Code                                    */
 /*****************************************************************************/
@@ -115,94 +244,128 @@ void InitLineInfo (void)
     static const FilePos DefaultPos = STATIC_FILEPOS_INITIALIZER;
 
     /* Increase the initial count of the line info collection */
-    CollGrow (&LineInfoColl, 200);
-
-    /* Allocate 8 slots */
-    AllocatedSlots = 8;
-    CurLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
+    CollGrow (&LineInfoList, 200);
 
-    /* Initalize the predefined slots. Be sure to create a new LineInfo for
-     * the default source. This is necessary to allow error message to be
-     * generated without any input file open.
+    /* Create a LineInfo for the default source. This is necessary to allow
+     * error message to be generated without any input file open.
      */
-    UsedSlots = 2;
-    CurLineInfo[LI_SLOT_ASM].Type = LI_TYPE_ASM;        /* Count = 0 */
-    CurLineInfo[LI_SLOT_ASM].Info = NewLineInfo (LI_TYPE_ASM, &DefaultPos);
-    CurLineInfo[LI_SLOT_EXT].Type = LI_TYPE_EXT;        /* Count = 0 */
-    CurLineInfo[LI_SLOT_EXT].Info = 0;
+    AsmLineInfo = StartLine (&DefaultPos, LI_TYPE_ASM, 0);
 }
 
 
 
-int AllocLineInfoSlot (unsigned Type, unsigned Count)
-/* Allocate a line info slot of the given type and return the slot index */
+void DoneLineInfo (void)
+/* Close down line infos */
 {
-    /* Grow the array if necessary */
-    if (UsedSlots >= AllocatedSlots) {
-        LineInfoSlot* NewLineInfo;
-        AllocatedSlots *= 2;
-        NewLineInfo = xmalloc (AllocatedSlots * sizeof (LineInfoSlot));
-        memcpy (NewLineInfo, CurLineInfo, UsedSlots * sizeof (LineInfoSlot));
-        xfree (CurLineInfo);
-        CurLineInfo = NewLineInfo;
+    /* Close all current line infos */
+    unsigned Count = CollCount (&CurLineInfo);
+    while (Count) {
+        EndLine (CollAt (&CurLineInfo, --Count));
     }
-
-    /* Array is now big enough, add the new data */
-    CurLineInfo[UsedSlots].Type = LI_MAKE_TYPE(Type, Count);
-    CurLineInfo[UsedSlots].Info = 0;
-
-    /* Increment the count and return the index of the new slot */
-    return (int) UsedSlots++;
 }
 
 
 
-void FreeLineInfoSlot (int Slot)
-/* Free the line info in the given slot. Note: Alloc/Free must be used in
- * FIFO order.
- */
+void EndLine (LineInfo* LI)
+/* End a line that is tracked by the given LineInfo structure */
 {
-    /* Check the parameter */
-    PRECONDITION (Slot == (int) UsedSlots - 1);
+    unsigned I;
+
+    /* Close the spans for the line */
+    CloseSpans (&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));
+    }
+    CollDeleteAll (&LI->OpenSpans);
+
+    /* Line info is no longer active - remove it from the list of current
+     * line infos.
+     */
+    CollDeleteItem (&CurLineInfo, LI);
 
-    /* Free the last entry */
-    CurLineInfo[Slot].Info = 0;
-    --UsedSlots;
+    /* 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);
+        }
+    }
 }
 
 
 
-void GenLineInfo (int Slot, const FilePos* Pos)
-/* Generate a new line info in the given slot */
+LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count)
+/* Start line info for a new line */
 {
-    /* Get a pointer to the slot */
-    LineInfoSlot* S = CurLineInfo + Slot;
+    LineInfoKey Key;
+    LineInfo* LI;
+
+    /* Prepare the key struct */
+    Key.Pos   = *Pos;
+    Key.Type  = Type;
+    Key.Count = Count;
 
-    /* Generate new data only if it is different from the existing. */
-    if (S->Info && CompareFilePos (&S->Info->Pos, Pos) == 0) {
-        /* Already there */
-        return;
+    /* 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);
+    if (LI == 0) {
+        /* Allocate a new LineInfo */
+        LI = NewLineInfo (&Key);
+    } else {
+        Key.Count = 2;
     }
 
-    /* Allocate new data */
-    S->Info = NewLineInfo (S->Type, Pos);
+    /* Open the spans for this line info */
+    OpenSpans (&LI->OpenSpans);
+
+    /* Add the line info to the list of current line infos */
+    CollAppend (&CurLineInfo, LI);
+
+    /* Return the new info */
+    return LI;
 }
 
 
 
-void ClearLineInfo (int Slot)
-/* Clear the line info in the given slot */
+void NewAsmLine (void)
+/* Start a new assembler input line. Use this function when generating new
+ * line of LI_TYPE_ASM. It will check if line and/or file have actually
+ * changed, end the old and start the new line as necessary.
+ */
 {
-    /* Zero the pointer */
-    CurLineInfo[Slot].Info = 0;
+    /* Check if we can reuse the old line */
+    if (AsmLineInfo) {
+        if (AsmLineInfo->Key.Pos.Line == CurTok.Pos.Line &&
+            AsmLineInfo->Key.Pos.Name == CurTok.Pos.Name) {
+            /* We do already have line info for this line */
+            return;
+        }
+
+        /* Line has changed -> end the old line */
+        EndLine (AsmLineInfo);
+    }
+
+    /* Start a new line using the current line info */
+    AsmLineInfo = StartLine (&CurTok.Pos, LI_TYPE_ASM, 0);
 }
 
 
 
-void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage)
-/* Return full line infos, that is line infos for all slots in LineInfos. The
- * function will clear LineInfos before usage and will increment the usage
- * counter by IncUsage for all line infos returned.
+void GetFullLineInfo (Collection* LineInfos, int ForceRef)
+/* 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.
  */
 {
     unsigned I;
@@ -210,66 +373,45 @@ void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage)
     /* Clear the collection */
     CollDeleteAll (LineInfos);
 
+    /* Grow the collection as necessary */
+    CollGrow (LineInfos, CollCount (&CurLineInfo));
+
     /* Copy all valid line infos to the collection */
-    for (I = 0; I < UsedSlots; ++I) {
+    for (I = 0; I < CollCount (&CurLineInfo); ++I) {
 
         /* Get the line info from the slot */
-        LineInfo* LI = CurLineInfo[I].Info;
+        LineInfo* LI = CollAt (&CurLineInfo, I);
 
-        /* Ignore empty slots */
-        if (LI) {
-            LI->Usage += IncUsage;
-            CollAppend (LineInfos, LI);
+        /* Mark it as referenced */
+        if (ForceRef) {
+            LI->Referenced = 1;
         }
+
+        /* Return it to the caller */
+        CollAppend (LineInfos, LI);
     }
 }
 
 
 
-LineInfo* ReleaseLineInfo (LineInfo* LI)
-/* Decrease the reference count of the given line info and return it. The
- * function will gracefully accept NULL pointers and do nothing in this case.
- */
+const FilePos* GetSourcePos (const LineInfo* LI)
+/* Return the source file position from the given line info */
 {
-    if (LI) {
-        /* Cannot decrease below zero */
-               CHECK (LI->Usage != 0);
-        --LI->Usage;
-    }
-    return LI;
+    return &LI->Key.Pos;
 }
 
 
 
-static int CmpLineInfo (void* Data attribute ((unused)),
-                       const void* LI1_, const void* LI2_)
-/* Compare function for the sort */
+unsigned GetLineInfoType (const LineInfo* LI)
+/* Return the type of a line info */
 {
-    /* Cast the pointers */
-    const LineInfo* LI1 = LI1_;
-    const LineInfo* LI2 = LI2_;
-
-    /* Unreferenced line infos are always larger, otherwise sort by file,
-     * then by line, then by column.
-     */
-    if ((LI1->Usage == 0) == (LI2->Usage == 0)) {
-       /* Both are either referenced or unreferenced */
-        return CompareFilePos (&LI1->Pos, &LI2->Pos);
-    } else {
-       if (LI1->Usage > 0) {
-           return -1;
-       } else {
-           return 1;
-       }
-    }
+    return LI_GET_TYPE (LI->Key.Type);
 }
 
 
 
 void WriteLineInfo (const Collection* LineInfos)
-/* Write a list of line infos to the object file. MakeLineInfoIndex has to
- * be called before!
- */
+/* Write a list of line infos to the object file. */
 {
     unsigned I;
 
@@ -282,40 +424,10 @@ void WriteLineInfo (const Collection* LineInfos)
         /* Get a pointer to the line info */
         const LineInfo* LI = CollConstAt (LineInfos, I);
 
-        /* Check the index */
-        CHECK (LI->Index != INV_LINEINFO_INDEX);
+        CHECK (LI->Id != ~0U);
 
         /* Write the index to the file */
-        ObjWriteVar (LI->Index);
-    }
-}
-
-
-
-void MakeLineInfoIndex (void)
-/* Index the line infos */
-{
-    unsigned I;
-
-    /* Sort the line info list */
-    CollSort (&LineInfoColl, CmpLineInfo, 0);
-
-    /* Walk over the list, index the line infos and count the used ones */
-    UsedLineInfoCount = 0;
-    for (I = 0; I < CollCount (&LineInfoColl); ++I) {
-       /* Get a pointer to this line info */
-       LineInfo* LI = CollAtUnchecked (&LineInfoColl, I);
-
-        /* If it is invalid, terminate the loop. All unused line infos were
-         * placed at the end of the collection by the sort.
-         */
-        if (LI->Usage == 0) {
-            break;
-        }
-
-        /* Index and count this one */
-        LI->Index = I;
-        ++UsedLineInfoCount;
+        ObjWriteVar (LI->Id);
     }
 }
 
@@ -330,18 +442,22 @@ void WriteLineInfos (void)
     ObjStartLineInfos ();
 
     /* Write the line info count to the list */
-    ObjWriteVar (UsedLineInfoCount);
+    ObjWriteVar (CollCount (&LineInfoList));
 
     /* Walk over the list and write all line infos */
-    for (I = 0; I < UsedLineInfoCount; ++I) {
+    for (I = 0; I < CollCount (&LineInfoList); ++I) {
+
         /* Get a pointer to this line info */
-        LineInfo* LI = CollAt (&LineInfoColl, I);
+        LineInfo* LI = CollAt (&LineInfoList, I);
+
+        /* Write the source file position */
+        ObjWritePos (&LI->Key.Pos);
 
         /* Write the type and count of the line info */
-        ObjWriteVar (LI->Type);
+        ObjWriteVar (LI_MAKE_TYPE (LI->Key.Type, LI->Key.Count));
 
-        /* Write the source file position */
-        ObjWritePos (&LI->Pos);
+        /* Write the spans for this line */
+        WriteSpans (&LI->Spans);
     }
 
     /* End of line infos */
index 14ca35f811d9b816bccb6fc806f33a32cbcb7205..17d2dfd438020d8914a67fe095f38655912210b4 100644 (file)
@@ -41,6 +41,7 @@
 /* common */
 #include "coll.h"
 #include "filepos.h"
+#include "hashtab.h"
 #include "lidefs.h"
 
 
 
 
 
-/* Predefined line info slots. These are allocated when initializing the
- * module. Beware: Some code relies on the fact that slot zero is the basic
- * standard line info. It is assumed to be always there.
- */
-enum {
-    LI_SLOT_INV         = -1,           /* Use to mark invalid slots */
-    LI_SLOT_ASM         = 0,            /* Normal assembler source */
-    LI_SLOT_EXT         = 1,            /* Externally supplied line info */
-};
-
-/* The LineInfo structure is shared between several fragments, so we need a
- * reference counter.
- */
+/* Opaque structure used to handle line information */
 typedef struct LineInfo LineInfo;
-struct LineInfo {
-    unsigned    Usage;                  /* Usage counter */
-    unsigned    Type;                   /* Type of line info */
-    unsigned    Index;                  /* Index */
-    FilePos     Pos;                    /* File position */
-};
 
 
 
@@ -83,58 +66,37 @@ struct LineInfo {
 void InitLineInfo (void);
 /* Initialize the line infos */
 
-int AllocLineInfoSlot (unsigned Type, unsigned Count);
-/* Allocate a line info slot of the given type and return the slot index */
-
-void FreeLineInfoSlot (int Slot);
-/* Free the line info in the given slot. Note: Alloc/Free must be used in
- * FIFO order.
- */
+void DoneLineInfo (void);
+/* Close down line infos */
 
-void GenLineInfo (int Slot, const FilePos* Pos);
-/* Generate a new line info in the given slot */
+void EndLine (LineInfo* LI);
+/* End a line that is tracked by the given LineInfo structure */
 
-void ClearLineInfo (int Slot);
-/* Clear the line info in the given slot */
+LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count);
+/* Start line info for a new line */
 
-void GetFullLineInfo (Collection* LineInfos, unsigned IncUsage);
-/* Return full line infos, that is line infos for all slots in LineInfos. The
- * function will clear LineInfos before usage and will increment the usage
- * counter by IncUsage for all line infos returned.
+void NewAsmLine (void);
+/* Start a new assembler input line. Use this function when generating new
+ * line of LI_TYPE_ASM. It will check if line and/or file have actually
+ * changed, end the old and start the new line as necessary.
  */
 
-LineInfo* ReleaseLineInfo (LineInfo* LI);
-/* Decrease the reference count of the given line info and return it. The
- * function will gracefully accept NULL pointers and do nothing in this case.
+void GetFullLineInfo (Collection* LineInfos, int ForceRef);
+/* 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.
  */
 
-#if defined(HAVE_INLINE)
-INLINE const FilePos* GetSourcePos (const LineInfo* LI)
+const FilePos* GetSourcePos (const LineInfo* LI);
 /* Return the source file position from the given line info */
-{
-    return &LI->Pos;
-}
-#else
-#  define GetSourcePos(LI)      (&(LI)->Pos)
-#endif
 
-#if defined(HAVE_INLINE)
-INLINE unsigned GetLineInfoType (const LineInfo* LI)
+unsigned GetLineInfoType (const LineInfo* LI);
 /* Return the type of a line info */
-{
-    return LI_GET_TYPE (LI->Type);
-}
-#else
-#  define GetLineInfoType(LI)     LI_GET_TYPE ((LI)->Type)
-#endif
 
 void WriteLineInfo (const Collection* LineInfos);
-/* Write a list of line infos to the object file. MakeLineInfoIndex has to
- * be called before!
- */
-
-void MakeLineInfoIndex (void);
-/* Index the line infos */
+/* Write a list of line infos to the object file. */
 
 void WriteLineInfos (void);
 /* Write a list of all line infos to the object file. */
index 34d7eaeb7548e7768855b67198f08e1ea4e657ed..b2fdaeaf79bb6075c8d19d17a431017a45852fd9 100644 (file)
@@ -65,7 +65,7 @@
 static unsigned HT_GenHash (const void* Key);
 /* Generate the hash over a key. */
 
-static const void* HT_GetKey (void* Entry);
+static const void* HT_GetKey (const void* Entry);
 /* Given a pointer to the user entry data, return a pointer to the key */
 
 static int HT_Compare (const void* Key1, const void* Key2);
@@ -130,7 +130,7 @@ struct MacExp {
     unsigned           ParamCount;     /* Number of actual parameters */
     TokNode**          Params;         /* List of actual parameters */
     TokNode*           ParamExp;       /* Node for expanding parameters */
-    int         LISlot;         /* Slot for additional line infos */
+    LineInfo*   LI;             /* Line info for the expansion */
 };
 
 /* Maximum number of nested macro expansions */
@@ -164,7 +164,7 @@ static unsigned HT_GenHash (const void* Key)
 
 
 
-static const void* HT_GetKey (void* Entry)
+static const void* HT_GetKey (const void* Entry)
 /* Given a pointer to the user entry data, return a pointer to the index */
 {
     return &((Macro*) Entry)->Name;
@@ -307,7 +307,7 @@ static MacExp* NewMacExp (Macro* M)
        E->Params[I] = 0;
     }
     E->ParamExp          = 0;
-    E->LISlot     = AllocLineInfoSlot (LI_TYPE_MACRO, MacExpansions);
+    E->LI         = 0;
 
     /* Mark the macro as expanding */
     ++M->Expansions;
@@ -344,8 +344,10 @@ static void FreeMacExp (MacExp* E)
     }
     xfree (E->Params);
 
-    /* Free the additional line info slot */
-    FreeLineInfoSlot (E->LISlot);
+    /* Free the additional line info */
+    if (E->LI) {
+        EndLine (E->LI);
+    }
 
     /* Free the final token if we have one */
     if (E->Final) {
@@ -644,8 +646,8 @@ static int MacExpand (void* Data)
 ExpandParam:
     if (Mac->ParamExp) {
 
-               /* Ok, use token from parameter list, but don't use its line info */
-               TokSet (Mac->ParamExp, LI_SLOT_INV);
+               /* Ok, use token from parameter list */
+               TokSet (Mac->ParamExp);
 
                /* Set pointer to next token */
                Mac->ParamExp = Mac->ParamExp->Next;
@@ -660,7 +662,13 @@ ExpandParam:
     if (Mac->Exp) {
 
                /* Use next macro token */
-               TokSet (Mac->Exp, Mac->LISlot);
+               TokSet (Mac->Exp);
+
+        /* Create new line info for this token */
+        if (Mac->LI) {
+            EndLine (Mac->LI);
+        }
+        Mac->LI = StartLine (&CurTok.Pos, LI_TYPE_MACRO, MacExpansions);
 
                /* Set pointer to next token */
                Mac->Exp = Mac->Exp->Next;
@@ -723,7 +731,7 @@ ExpandParam:
     if (Mac->Final) {
 
        /* Set the final token and remove it */
-       TokSet (Mac->Final, LI_SLOT_INV);
+       TokSet (Mac->Final);
        FreeTokNode (Mac->Final);
        Mac->Final = 0;
 
index 30f22da14c0e905f6a1e78c0f43c146f6b6a15bf..1104f5b68a8350217bf50ef31ce2769f4d1fd2af 100644 (file)
@@ -1036,15 +1036,15 @@ int main (int argc, char* argv [])
         CheckAssertions ();
     }
 
-    /* If we didn't have an errors, index the line infos */
-    MakeLineInfoIndex ();
-
     /* Dump the data */
     if (Verbosity >= 2) {
         SymDump (stdout);
         SegDump ();
     }
 
+    /* If we didn't have an errors, finish off the line infos */
+    DoneLineInfo ();
+
     /* If we didn't have any errors, create the object, listing and
      * dependency files
      */
index c921562eed1539c1aed9cc35fe3b549e2ebedca6..bb31799dc81ecf2046cec85e3911dcbc325b8bdb 100644 (file)
@@ -122,8 +122,8 @@ struct CharSource {
 
 /* Current input variables */
 static CharSource* Source       = 0;    /* Current char source */
-static unsigned            FCount      = 0;    /* Count of input files */
-static int         C           = 0;    /* Current input character */
+static unsigned           FCount       = 0;    /* Count of input files */
+static int                   = 0;    /* Current input character */
 
 /* Force end of assembly */
 int              ForcedEnd     = 0;
@@ -818,7 +818,7 @@ static int Sweet16Reg (const StrBuf* Id)
 void NextRawTok (void)
 /* Read the next raw token from the input stream */
 {
-    Macro* M;                
+    Macro* M;
 
     /* If we've a forced end of assembly, don't read further */
     if (ForcedEnd) {
@@ -831,7 +831,7 @@ Restart:
     if (InputFromStack ()) {
         if (CurTok.Tok == TOK_IDENT && (M = FindDefine (&CurTok.SVal)) != 0) {
             /* This is a define style macro - expand it */
-            MacExpandStart (M);          
+            MacExpandStart (M);
             goto Restart;
         }
         return;
@@ -852,7 +852,7 @@ Again:
     SB_Clear (&CurTok.SVal);
 
     /* Generate line info for the current token */
-    GenLineInfo (LI_SLOT_ASM, &CurTok.Pos);
+    NewAsmLine ();
 
     /* Hex number or PC symbol? */
     if (C == '$') {
@@ -901,7 +901,7 @@ Again:
                CurTok.IVal = 0;
            }
            CurTok.IVal = (CurTok.IVal << 1) + DigitVal (C);
-           NextChar ();
+           NextChar ();
        }
 
        /* This is an integer constant */
@@ -1097,7 +1097,7 @@ Again:
                     break;
 
                default:
-                   break;
+                   break;
            }
 
        } else if (CPU == CPU_SWEET16 &&
@@ -1195,7 +1195,7 @@ CharAgain:
            NextChar ();
            switch (C) {
 
-               case ':':
+               case ':':
                    NextChar ();
                    CurTok.Tok = TOK_NAMESPACE;
                    break;
@@ -1244,7 +1244,7 @@ CharAgain:
        case '#':
            NextChar ();
            CurTok.Tok = TOK_HASH;
-           return;
+           return;
 
        case '(':
            NextChar ();
@@ -1342,7 +1342,7 @@ CharAgain:
                }
                CurTok.IVal = C;
                CurTok.Tok = TOK_CHARCON;
-               NextChar ();
+               NextChar ();
                if (C != '\'') {
                     if (!MissingCharTerm) {
                         Error ("Illegal character constant");
index 69d44ca45489a32758a18a13f25c0d7112c4735b..e7339e78c595326294db4b61f878a32b9163db46 100644 (file)
@@ -165,7 +165,9 @@ void WriteSpans (const Collection* Spans)
         /* Get next range */
         const Span* S = CollConstAt (Spans, I);
 
-        /* Write data for th span We will write the size instead of the end
+        CHECK (S->End > S->Start);
+
+        /* Write data for the span We will write the size instead of the end
          * offset to save some bytes, since most spans are expected to be
          * rather small.
          */
index efd5bc1053bf92559c154934711d64f3d60f5aa1..e79f1808a567a3cfef284f8caf1d2c4ed3525fd1 100644 (file)
@@ -82,20 +82,12 @@ void FreeTokNode (TokNode* N)
 
 
 
-void TokSet (TokNode* N, int LineInfoSlot)
-/* Set the scanner token from the given token node. If the given line info
- * slot is not LI_SLOT_INV, it is used to store the position of the token fed
- * into the scanner.
- */
+void TokSet (TokNode* N)
+/* Set the scanner token from the given token node. */
 {
     /* Set the values */
     CopyToken (&CurTok, &N->T);
     SB_Terminate (&CurTok.SVal);
-
-    /* Set the position if the slot is not invald */
-    if (LineInfoSlot != LI_SLOT_INV) {
-        GenLineInfo (LineInfoSlot, &CurTok.Pos);
-    }
 }
 
 
@@ -227,7 +219,10 @@ static int ReplayTokList (void* List)
     CHECK (L->Last != 0);
 
     /* Set the next token from the list */
-    TokSet (L->Last, LI_SLOT_ASM);
+    TokSet (L->Last);
+
+    /* Set the line info for the new token */
+    NewAsmLine ();
 
     /* If a check function is defined, call it, so it may look at the token
      * just set and changed it as apropriate.
index 145c5f25a1402a0616cae06f5f5e616edeb0ffed..b449ad9a0fca21d04a72d331ed4af785c4d780f0 100644 (file)
@@ -95,11 +95,8 @@ TokNode* NewTokNode (void);
 void FreeTokNode (TokNode* N);
 /* Free the given token node */
 
-void TokSet (TokNode* N, int LineInfoSlot);
-/* Set the scanner token from the given token node. If the given line info
- * slot is not LI_SLOT_INV, it is used to store the position of the token fed
- * into the scanner.
- */
+void TokSet (TokNode* N);
+/* Set the scanner token from the given token node. */
 
 enum TC TokCmp (const TokNode* N);
 /* Compare the token given as parameter against the current token */