/* 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);
}
-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);
+}