]> git.sur5r.net Git - cc65/commitdiff
Some improvements for spans.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 7 Aug 2011 20:01:40 +0000 (20:01 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sun, 7 Aug 2011 20:01:40 +0000 (20:01 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@5134 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/ca65/segment.c
src/ca65/span.c
src/ca65/span.h
src/ca65/symtab.c

index a089a5d88b1611a67d42cb9e09d97b346bb5780f..004bf45abe0b360a5f463efd02068bf0a43d0afc 100644 (file)
@@ -457,6 +457,50 @@ void SegDump (void)
 
 
 
+void InitSegments (void)
+/* Initialize segments */
+{
+    /* Create the predefined segments. Code segment is active */
+    ActiveSeg = NewSegFromDef (&CodeSegDef);
+    NewSegFromDef (&RODataSegDef);
+    NewSegFromDef (&BssSegDef);
+    NewSegFromDef (&DataSegDef);
+    NewSegFromDef (&ZeropageSegDef);
+    NewSegFromDef (&NullSegDef);
+}
+
+
+
+void SetSegmentSizes (void)
+/* Set the default segment sizes according to the memory model */
+{
+    /* Initialize segment sizes. The segment definitions do already contain
+     * the correct values for the default case (near), so we must only change
+     * things that should be different.
+     */
+    switch (MemoryModel) {
+
+        case MMODEL_NEAR:
+            break;
+
+        case MMODEL_FAR:
+            CodeSegDef.AddrSize = ADDR_SIZE_FAR;
+            break;
+
+        case MMODEL_HUGE:
+            CodeSegDef.AddrSize   = ADDR_SIZE_FAR;
+            DataSegDef.AddrSize   = ADDR_SIZE_FAR;
+            BssSegDef.AddrSize    = ADDR_SIZE_FAR;
+            RODataSegDef.AddrSize = ADDR_SIZE_FAR;
+            break;
+
+        default:
+            Internal ("Invalid memory model: %d", MemoryModel);
+    }
+}
+
+
+
 static void WriteOneSeg (Segment* Seg)
 /* Write one segment to the object file */
 {
@@ -541,50 +585,6 @@ static void WriteOneSeg (Segment* Seg)
 
 
 
-void InitSegments (void)
-/* Initialize segments */
-{
-    /* Create the predefined segments. Code segment is active */
-    ActiveSeg = NewSegFromDef (&CodeSegDef);
-    NewSegFromDef (&RODataSegDef);
-    NewSegFromDef (&BssSegDef);
-    NewSegFromDef (&DataSegDef);
-    NewSegFromDef (&ZeropageSegDef);
-    NewSegFromDef (&NullSegDef);
-}
-
-
-
-void SetSegmentSizes (void)
-/* Set the default segment sizes according to the memory model */
-{
-    /* Initialize segment sizes. The segment definitions do already contain
-     * the correct values for the default case (near), so we must only change
-     * things that should be different.
-     */
-    switch (MemoryModel) {
-
-        case MMODEL_NEAR:
-            break;
-
-        case MMODEL_FAR:
-            CodeSegDef.AddrSize = ADDR_SIZE_FAR;
-            break;
-
-        case MMODEL_HUGE:
-            CodeSegDef.AddrSize   = ADDR_SIZE_FAR;
-            DataSegDef.AddrSize   = ADDR_SIZE_FAR;
-            BssSegDef.AddrSize    = ADDR_SIZE_FAR;
-            RODataSegDef.AddrSize = ADDR_SIZE_FAR;
-            break;
-
-        default:
-            Internal ("Invalid memory model: %d", MemoryModel);
-    }
-}
-
-
-
 void WriteSegments (void)
 /* Write the segment data to the object file */
 {
index 70bc85167c11ffdc8aec8ed6ddd9def4bdc09234..47db633b0b878e7a0fffaa4bb03a81c147e67403 100644 (file)
 
 
 /*****************************************************************************/
-/*                                          Code                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
 
-Span* NewSpan (struct Segment* Seg)
+/*****************************************************************************/
+/*                                   Code                                    */
+/*****************************************************************************/
+
+
+
+static Span* NewSpan (Segment* Seg, unsigned long Start, unsigned long End)
 /* Create a new span. The segment is set to Seg, Start and End are set to the
  * current PC of the segment.
  */
@@ -59,8 +65,8 @@ Span* NewSpan (struct Segment* Seg)
 
     /* Initialize the struct */
     S->Seg      = Seg;
-    S->Start    = Seg->PC;
-    S->End      = Seg->PC;
+    S->Start    = Start;
+    S->End      = End;
 
     /* Return the new struct */
     return S;
@@ -68,15 +74,24 @@ Span* NewSpan (struct Segment* Seg)
 
 
 
-void AddSpans (Collection* Spans)
-/* Add a span for all existing segments to the given collection of spans. The
- * currently active segment will be inserted first with all others following.
+static void FreeSpan (Span* S)
+/* Free a span */
+{
+    xfree (S);
+}
+
+
+
+void OpenSpans (Collection* Spans)
+/* Open a list of spans for all existing segments to the given collection of
+ * spans. The currently active segment will be inserted first with all others
+ * following.
  */
 {
     unsigned I;
 
     /* Add the currently active segment */
-    CollAppend (Spans, NewSpan (ActiveSeg));
+    CollAppend (Spans, NewSpan (ActiveSeg, ActiveSeg->PC, ActiveSeg->PC));
 
     /* Walk through the segment list and add all other segments */
     for (I = 0; I < CollCount (&SegmentList); ++I) {
@@ -84,7 +99,7 @@ void AddSpans (Collection* Spans)
 
         /* Be sure to skip the active segment, since it was already added */
         if (Seg != ActiveSeg) {
-            CollAppend (Spans, NewSpan (Seg));
+            CollAppend (Spans, NewSpan (Seg, Seg->PC, Seg->PC));
         }
     }
 }
@@ -92,19 +107,43 @@ void AddSpans (Collection* Spans)
 
 
 void CloseSpans (Collection* Spans)
-/* Close all open spans by setting PC to the current PC for the segment. */
+/* Close a list of spans. This will add new segments to the list, mark the end
+ * of existing ones, and remove empty spans from the list.
+ */
 {
-    unsigned I;
+    unsigned I, J;
 
-    /* Walk over the segment list */
-    for (I = 0; I < CollCount (Spans); ++I) {
+    /* Have new segments been added while the span list was open? */
+    for (I = CollCount (Spans); I < CollCount (&SegmentList); ++I) {
+
+        /* Add new spans if not empty */
+        Segment* S = CollAtUnchecked (&SegmentList, I);
+        if (S->PC == 0) {
+            /* Segment is empty */
+            continue;
+        }
+        CollAppend (Spans, NewSpan (S, 0, S->PC));
+    }
 
-        /* Get the next segment range */
+    /* Walk over the spans, close open, remove empty ones */
+    for (I = 0, J = 0; I < CollCount (Spans); ++I) {
+
+        /* Get the next span */
         Span* S = CollAtUnchecked (Spans, I);
 
         /* Set the end offset */
-        S->End = S->Seg->PC;
+        if (S->Start == S->Seg->PC) {
+            /* Span is empty */
+            FreeSpan (S);
+        } else {
+            /* Span is not empty */
+            S->End = S->Seg->PC;
+            CollReplace (Spans, S, J++);
+        }
     }
+
+    /* New Count is now in J */
+    Spans->Count = J;
 }
 
 
@@ -113,23 +152,9 @@ void WriteSpans (const Collection* Spans)
 /* Write a list of spans to the output file */
 {
     unsigned I;
-    unsigned Count;
-
-    /* Determine how many of the segments contain actual data */
-    Count = 0;
-    for (I = 0; I < CollCount (Spans); ++I) {
 
-        /* Get next range */
-        const Span* S = CollConstAt (Spans, I);
-
-        /* Is this segment range empty? */
-        if (S->Start != S->End) {
-            ++Count;
-        }
-    }
-
-    /* Write the number of spans with data */
-    ObjWriteVar (Count);
+    /* Write the number of spans */
+    ObjWriteVar (CollCount (Spans));
 
     /* Write the spans */
     for (I = 0; I < CollCount (Spans); ++I) {
@@ -137,15 +162,13 @@ void WriteSpans (const Collection* Spans)
         /* Get next range */
         const Span* S = CollConstAt (Spans, I);
 
-        /* Write data for non empty spans. We will write the size instead of
-         * the end offset to save some bytes, since most spans are expected
-         * to be rather small.
+        /* Write data for th span We will write the size instead of the end
+         * offset to save some bytes, since most spans are expected to be
+         * rather small.
          */
-        if (S->Start != S->End) {
-            ObjWriteVar (S->Seg->Num);
-            ObjWriteVar (S->Start);
-            ObjWriteVar (S->End - S->Start);
-        }
+        ObjWriteVar (S->Seg->Num);
+        ObjWriteVar (S->Start);
+        ObjWriteVar (S->End - S->Start);
     }
 }
 
index 8bbc7c1f376d66189ff2fb37ed99c98b04bc9250..407c753d90d564caf4e1ea3bab05f0a1db5c9610 100644 (file)
@@ -53,6 +53,7 @@
 /* Span definition */
 typedef struct Span Span;
 struct Span{
+    unsigned        Id;                 /* Span id */
     struct Segment* Seg;                       /* Pointer to segment */
     unsigned long   Start;              /* Start of range */
     unsigned long   End;                /* End of range */
@@ -66,11 +67,6 @@ struct Span{
 
 
 
-Span* NewSpan (struct Segment* Seg);
-/* Create a new span. The segment is set to Seg, Start and End are set to the
- * current PC of the segment.
- */
-
 #if defined(HAVE_INLINE)
 INLINE unsigned long GetSpanSize (const Span* R)
 /* Return the span size in bytes */
@@ -81,9 +77,10 @@ INLINE unsigned long GetSpanSize (const Span* R)
 #  define GetSpanSize(R)   ((R)->End - (R)->Start)
 #endif
 
-void AddSpans (Collection* Spans);
-/* Add a span for all existing segments to the given collection of spans. The
- * currently active segment will be inserted first with all others following.
+void OpenSpans (Collection* Spans);
+/* Open a list of spans for all existing segments to the given collection of
+ * spans. The currently active segment will be inserted first with all others
+ * following.
  */
 
 void CloseSpans (Collection* Spans);
index 3b83b81674ba8656776ed07c09612a093825e3bf..409a49669b6283fc6b7612f18238a9829ce2cfdf 100644 (file)
@@ -223,7 +223,7 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
      * space in any segment).
      */
     if (CurrentScope->Type <= SCOPE_HAS_DATA) {
-        AddSpans (&CurrentScope->Spans);
+        OpenSpans (&CurrentScope->Spans);
     }
 }