]> git.sur5r.net Git - cc65/blobdiff - src/ld65/span.c
Even more optimization, cleanup, bugfix, comments.
[cc65] / src / ld65 / span.c
index f1bf280c3e20218f5cd32bb89f346200fe058cef..498ab762ada2e9cac0729cb4af36841a70f5b971 100644 (file)
 
 
 /* common */
+#include "gentype.h"
 #include "xmalloc.h"
 
-/* ld65 */           
+/* ld65 */
 #include "fileio.h"
 #include "objdata.h"
 #include "segments.h"
 #include "span.h"
+#include "tpool.h"
 
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 
-Span* NewSpan (struct Segment* Seg, unsigned long Offs, unsigned long Size)
+/* Definition of a span */
+struct Span {
+    unsigned            Id;             /* Id of the span */
+    unsigned            Sec;            /* Section id of this span */
+    unsigned long       Offs;           /* Offset of span within segment */
+    unsigned long       Size;           /* Size of span */
+    unsigned            Type;           /* Generic type of the data */
+};
+
+
+
+/*****************************************************************************/
+/*                                   Code                                    */
+/*****************************************************************************/
+
+
+
+static Span* NewSpan (unsigned Id)
 /* Create and return a new span */
 {
     /* Allocate memory */
-    Span* S = xmalloc (sizeof (*S));
+    Span* S = xmalloc (sizeof (Span));
 
-    /* Initialize the fields */
-    S->Seg      = Seg;
-    S->Offs     = Offs;
-    S->Size     = Size;
+    /* Initialize the fields as necessary */
+    S->Id       = Id;
 
     /* Return the result */
-   return S;
+    return S;
 }
 
 
 
-Span* ReadSpan (FILE* F, ObjData* O)
+Span* ReadSpan (FILE* F, ObjData* O, unsigned Id)
 /* Read a Span from a file and return it */
 {
-    /* Read the section id and translate it to a section pointer */
-    Section* Sec = GetObjSection (O, ReadVar (F));
-
-    /* Read the offset and relocate it */
-    unsigned long Offs = ReadVar (F) + Sec->Offs;
+    unsigned Type;
+
+    /* Create a new Span and initialize it */
+    Span* S = NewSpan (Id);
+    S->Sec  = ReadVar (F);
+    S->Offs = ReadVar (F);
+    S->Size = ReadVar (F);
+
+    /* Read the type. An id of zero means an empty string (no need to check) */
+    Type    = ReadVar (F);
+    if (Type == 0) {
+        S->Type = INVALID_TYPE_ID;
+    } else {
+        S->Type = GetTypeId (GetObjString (O, Type));
+    }
 
-    /* Create and return a new Span */
-    return NewSpan (Sec->Seg, Offs, ReadVar (F));
+    /* Return the new span */
+    return S;
 }
 
 
 
-void ReadSpans (Collection* Spans, FILE* F, ObjData* O)
-/* Read a list of Spans from a file and return it */
+unsigned* ReadSpanList (FILE* F)
+/* Read a list of span ids from a file. The list is returned as an array of
+** unsigneds, the first being the number of spans (never zero) followed by
+** the span ids. If the number of spans is zero, NULL is returned.
+*/
 {
+    unsigned* Spans;
+
     /* First is number of Spans */
     unsigned Count = ReadVar (F);
+    if (Count == 0) {
+        return 0;
+    }
 
-    /* Preallocate enough entries in the collection */
-    CollGrow (Spans, Count);
+    /* Allocate memory for the list and set the count */
+    Spans  = xmalloc ((Count + 1) * sizeof (*Spans));
+    *Spans = Count;
 
     /* Read the spans and add them */
-    while (Count--) {
-        CollAppend (Spans, ReadSpan (F, O));
+    while (Count) {
+        Spans[Count] = ReadVar (F);
+        --Count;
+    }
+
+    /* Return the list */
+    return Spans;
+}
+
+
+
+unsigned* DupSpanList (const unsigned* S)
+/* Duplicate a span list */
+{
+    unsigned Size;
+
+    /* The list may be empty */
+    if (S == 0) {
+        return 0;
     }
+
+    /* Allocate memory, copy and return the new list */
+    Size = (*S + 1) * sizeof (*S);
+    return memcpy (xmalloc (Size), S, Size);
 }
 
 
@@ -108,56 +165,83 @@ void FreeSpan (Span* S)
 
 
 
-void AddSpan (Collection* Spans, struct Segment* Seg, unsigned long Offs,
-              unsigned long Size)
-/* Either add a new span to the ones already in the given collection, or - if
- * possible - merge it with adjacent ones that already exist.
- */
+unsigned SpanCount (void)
+/* Return the total number of spans */
 {
+    /* Walk over all object files */
     unsigned I;
+    unsigned Count = 0;
+    for (I = 0; I < CollCount (&ObjDataList); ++I) {
 
-    /* We don't have many spans in a collection, so we do a linear search here.
-     * The collection is kept sorted which eases our work here.
-     */
-    for (I = 0; I < CollCount (Spans); ++I) {
+        /* Get this object file */
+        const ObjData* O = CollAtUnchecked (&ObjDataList, I);
 
-        /* Get the next span */
-       Span* S = CollAtUnchecked (Spans, I);
+        /* Count spans */
+        Count += CollCount (&O->Spans);
+    }
+
+    return Count;
+}
 
-        /* Must be same segment, otherwise we cannot merge */
-        if (S->Seg != Seg) {
-            continue;
+
+
+void PrintDbgSpanList (FILE* F, const ObjData* O, const unsigned* List)
+/* Output a string ",span=x[+y...]" for the given list. If the list is empty
+** or NULL, output nothing. This is a helper function for other modules to
+** print a list of spans read by ReadSpanList to the debug info file.
+*/
+{
+    if (List && *List) {
+        unsigned I;
+        const char* Format = ",span=%u";
+        for (I = 0; I < *List; ++I) {
+            fprintf (F, Format, O->SpanBaseId + List[I+1]);
+            Format = "+%u";
         }
+    }
+}
 
-        /* Check if we can merge it */
-        if (Offs < S->Offs) {
-
-            /* Got the insert position */
-            if (Offs + Size == S->Offs) {
-                /* Merge the two */
-                S->Offs = Offs;
-                S->Size += Size;
-            } else {
-                /* Insert a new entry */
-                CollInsert (Spans, NewSpan (Seg, Offs, Size), I);
-            }
 
-            /* Done */
-            return;
 
-        } else if (S->Offs + S->Size == Offs) {
+void PrintDbgSpans (FILE* F)
+/* Output the spans to a debug info file */
+{
+    unsigned I, J;
+    StrBuf SpanType = STATIC_STRBUF_INITIALIZER;
 
-            /* This is the regular case. Merge the two. */
-            S->Size += Size;
 
-            /* Done */
-            return;
-        }
-    }
+    /* Walk over all object files */
+    for (I = 0; I < CollCount (&ObjDataList); ++I) {
 
-    /* We must append an entry */
-    CollAppend (Spans, NewSpan (Seg, Offs, Size));
-}
+        /* Get this object file */
+        ObjData* O = CollAtUnchecked (&ObjDataList, I);
+
+        /* Walk over all spans in this object file */
+        for (J = 0; J < CollCount (&O->Spans); ++J) {
+
+            /* Get this span */
+            const Span* S = CollAtUnchecked (&O->Spans, J);
+
+            /* Get the section for this span */
+            const Section* Sec = GetObjSection (O, S->Sec);
 
+            /* Output the data */
+            fprintf (F, "span\tid=%u,seg=%u,start=%lu,size=%lu",
+                     O->SpanBaseId + S->Id,
+                     Sec->Seg->Id,
+                     Sec->Offs + S->Offs,
+                     S->Size);
 
+            /* If we have a type, add it */
+            if (S->Type != INVALID_TYPE_ID) {
+                fprintf (F, ",type=%u", S->Type);
+            }
 
+            /* Terminate the output line */
+            fputc ('\n', F);
+        }
+    }
+
+    /* Free the string buffer */
+    SB_Done (&SpanType);
+}