mirror of
https://github.com/cc65/cc65.git
synced 2024-09-30 08:57:49 +00:00
Write spans out in a separate object file section. This allows to merge
duplicate spans in an object file and more extensions to come. git-svn-id: svn://svn.cc65.org/cc65/trunk@5250 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
37ac033370
commit
358ccf236e
@ -116,6 +116,8 @@ static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
|
|||||||
H->AssertSize = Read32 (Obj);
|
H->AssertSize = Read32 (Obj);
|
||||||
H->ScopeOffs = Read32 (Obj);
|
H->ScopeOffs = Read32 (Obj);
|
||||||
H->ScopeSize = Read32 (Obj);
|
H->ScopeSize = Read32 (Obj);
|
||||||
|
H->SpanOffs = Read32 (Obj);
|
||||||
|
H->SpanSize = Read32 (Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -272,7 +272,7 @@ void EndLine (LineInfo* LI)
|
|||||||
/* End a line that is tracked by the given LineInfo structure */
|
/* End a line that is tracked by the given LineInfo structure */
|
||||||
{
|
{
|
||||||
/* Close the spans for the line */
|
/* 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
|
/* Move the spans to the list of all spans for this line, then clear the
|
||||||
* list of open spans.
|
* list of open spans.
|
||||||
@ -308,7 +308,7 @@ LineInfo* StartLine (const FilePos* Pos, unsigned Type, unsigned Count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Open the spans for this line info */
|
/* Open the spans for this line info */
|
||||||
OpenSpans (&LI->OpenSpans);
|
OpenSpanList (&LI->OpenSpans);
|
||||||
|
|
||||||
/* Add the line info to the list of current line infos */
|
/* Add the line info to the list of current line infos */
|
||||||
CollAppend (&CurLineInfo, LI);
|
CollAppend (&CurLineInfo, LI);
|
||||||
@ -447,8 +447,6 @@ void WriteLineInfos (void)
|
|||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
|
||||||
Collection EmptySpans = STATIC_COLLECTION_INITIALIZER;
|
|
||||||
|
|
||||||
/* Tell the object file module that we're about to write line infos */
|
/* Tell the object file module that we're about to write line infos */
|
||||||
ObjStartLineInfos ();
|
ObjStartLineInfos ();
|
||||||
|
|
||||||
@ -467,22 +465,12 @@ void WriteLineInfos (void)
|
|||||||
/* Write the type and count of the line info */
|
/* Write the type and count of the line info */
|
||||||
ObjWriteVar (LI->Key.Type);
|
ObjWriteVar (LI->Key.Type);
|
||||||
|
|
||||||
/* Spans are only added to the debug file if debug information is
|
/* Write the ids of the spans for this line */
|
||||||
* requested. Otherwise we write an empty list.
|
WriteSpanList (&LI->Spans);
|
||||||
*/
|
|
||||||
if (DbgSyms) {
|
|
||||||
WriteSpans (&LI->Spans);
|
|
||||||
} else {
|
|
||||||
/* Write out an empty list */
|
|
||||||
WriteSpans (&EmptySpans);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* End of line infos */
|
/* End of line infos */
|
||||||
ObjEndLineInfos ();
|
ObjEndLineInfos ();
|
||||||
|
|
||||||
/* For the sake of completeness, but not really necessary */
|
|
||||||
DoneCollection (&EmptySpans);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "segment.h"
|
#include "segment.h"
|
||||||
#include "sizeof.h"
|
#include "sizeof.h"
|
||||||
|
#include "span.h"
|
||||||
#include "spool.h"
|
#include "spool.h"
|
||||||
#include "symbol.h"
|
#include "symbol.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
@ -822,6 +823,9 @@ static void CreateObjFile (void)
|
|||||||
/* Write the assertions */
|
/* Write the assertions */
|
||||||
WriteAssertions ();
|
WriteAssertions ();
|
||||||
|
|
||||||
|
/* Write the spans */
|
||||||
|
WriteSpans ();
|
||||||
|
|
||||||
/* Write an updated header and close the file */
|
/* Write an updated header and close the file */
|
||||||
ObjClose ();
|
ObjClose ();
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||||
/* Römerstraße 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@ -86,6 +86,8 @@ static ObjHeader Header = {
|
|||||||
0, /* 32: Size of assertion table */
|
0, /* 32: Size of assertion table */
|
||||||
0, /* 32: Offset into scope table */
|
0, /* 32: Offset into scope table */
|
||||||
0, /* 32: Size of scope table */
|
0, /* 32: Size of scope table */
|
||||||
|
0, /* 32: Offset into span table */
|
||||||
|
0, /* 32: Size of span table */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -142,6 +144,8 @@ static void ObjWriteHeader (void)
|
|||||||
ObjWrite32 (Header.AssertSize);
|
ObjWrite32 (Header.AssertSize);
|
||||||
ObjWrite32 (Header.ScopeOffs);
|
ObjWrite32 (Header.ScopeOffs);
|
||||||
ObjWrite32 (Header.ScopeSize);
|
ObjWrite32 (Header.ScopeSize);
|
||||||
|
ObjWrite32 (Header.SpanOffs);
|
||||||
|
ObjWrite32 (Header.SpanSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -495,3 +499,19 @@ void ObjEndScopes (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ObjStartSpans (void)
|
||||||
|
/* Mark the start of the span table */
|
||||||
|
{
|
||||||
|
Header.SpanOffs = ftell (F);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ObjEndSpans (void)
|
||||||
|
/* Mark the end of the span table */
|
||||||
|
{
|
||||||
|
Header.SpanSize = ftell (F) - Header.SpanOffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||||
/* Römerstraße 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@ -149,6 +149,12 @@ void ObjStartScopes (void);
|
|||||||
void ObjEndScopes (void);
|
void ObjEndScopes (void);
|
||||||
/* Mark the end of the scope table */
|
/* Mark the end of the scope table */
|
||||||
|
|
||||||
|
void ObjStartSpans (void);
|
||||||
|
/* Mark the start of the span table */
|
||||||
|
|
||||||
|
void ObjEndSpans (void);
|
||||||
|
/* Mark the end of the span table */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of objfile.h */
|
/* End of objfile.h */
|
||||||
|
251
src/ca65/span.c
251
src/ca65/span.c
@ -34,21 +34,107 @@
|
|||||||
|
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "hashfunc.h"
|
||||||
|
#include "hashtab.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* ca65 */
|
/* ca65 */
|
||||||
|
#include "global.h"
|
||||||
#include "objfile.h"
|
#include "objfile.h"
|
||||||
#include "segment.h"
|
#include "segment.h"
|
||||||
#include "span.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Hash table functions */
|
||||||
|
static const HashFunctions HashFunc = {
|
||||||
|
HT_GenHash,
|
||||||
|
HT_GetKey,
|
||||||
|
HT_Compare
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Span hash table */
|
||||||
|
static HashTable SpanTab = STATIC_HASHTABLE_INITIALIZER (1051, &HashFunc);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Hash table functions */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned HT_GenHash (const void* Key)
|
||||||
|
/* Generate the hash over a key. */
|
||||||
|
{
|
||||||
|
/* Key is a Span pointer */
|
||||||
|
const Span* S = Key;
|
||||||
|
|
||||||
|
/* Hash over a combination of segment number, start and end */
|
||||||
|
return HashInt ((S->Seg->Num << 28) ^ (S->Start << 14) ^ S->End);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const void* HT_GetKey (const void* Entry)
|
||||||
|
/* Given a pointer to the user entry data, return a pointer to the key */
|
||||||
|
{
|
||||||
|
return Entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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 Span pointers */
|
||||||
|
const Span* S1 = Key1;
|
||||||
|
const Span* S2 = Key2;
|
||||||
|
|
||||||
|
/* Compare segment number, then start and end */
|
||||||
|
int Res = (int)S2->Seg->Num - (int)S1->Seg->Num;
|
||||||
|
if (Res == 0) {
|
||||||
|
Res = (int)S2->Start - (int)S1->Start;
|
||||||
|
if (Res == 0) {
|
||||||
|
Res = (int)S2->End - (int)S1->End;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Done */
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -64,9 +150,12 @@ static Span* NewSpan (Segment* Seg, unsigned long Start, unsigned long End)
|
|||||||
Span* S = xmalloc (sizeof (Span));
|
Span* S = xmalloc (sizeof (Span));
|
||||||
|
|
||||||
/* Initialize the struct */
|
/* Initialize the struct */
|
||||||
|
InitHashNode (&S->Node);
|
||||||
|
S->Id = ~0U;
|
||||||
S->Seg = Seg;
|
S->Seg = Seg;
|
||||||
S->Start = Start;
|
S->Start = Start;
|
||||||
S->End = End;
|
S->End = End;
|
||||||
|
S->Type = 0;
|
||||||
|
|
||||||
/* Return the new struct */
|
/* Return the new struct */
|
||||||
return S;
|
return S;
|
||||||
@ -82,7 +171,68 @@ static void FreeSpan (Span* S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OpenSpans (Collection* Spans)
|
static Span* MergeSpan (Span* S)
|
||||||
|
/* Check if we have a span with the same data as S already. If so, free S and
|
||||||
|
* return the already existing one. If not, remember S and return it.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Check if we have such a span already. If so use the existing
|
||||||
|
* one and free the one from the collection. If not, add the one to
|
||||||
|
* the hash table and return it.
|
||||||
|
*/
|
||||||
|
Span* E = HT_Find (&SpanTab, S);
|
||||||
|
if (E) {
|
||||||
|
/* If S has a type and E not, move the type */
|
||||||
|
CHECK (E->Type == 0);
|
||||||
|
E->Type = S->Type;
|
||||||
|
S->Type = 0;
|
||||||
|
/* Free S and return E */
|
||||||
|
FreeSpan (S);
|
||||||
|
return E;
|
||||||
|
} else {
|
||||||
|
/* Assign the id, insert S, then return it */
|
||||||
|
S->Id = HT_GetCount (&SpanTab);
|
||||||
|
HT_Insert (&SpanTab, S);
|
||||||
|
return S;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Span* OpenSpan (void)
|
||||||
|
/* Open a span for the active segment and return it. */
|
||||||
|
{
|
||||||
|
return NewSpan (ActiveSeg, ActiveSeg->PC, ActiveSeg->PC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Span* CloseSpan (Span* S)
|
||||||
|
/* Close the given span. Be sure to replace the passed span by the one
|
||||||
|
* returned, since the span will get deleted if it is empty or may be
|
||||||
|
* replaced if a duplicate exists.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Set the end offset */
|
||||||
|
if (S->Start == S->Seg->PC) {
|
||||||
|
/* Span is empty */
|
||||||
|
FreeSpan (S);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
/* Span is not empty */
|
||||||
|
S->End = S->Seg->PC;
|
||||||
|
|
||||||
|
/* Check if we have such a span already. If so use the existing
|
||||||
|
* one and free the one from the collection. If not, add the one to
|
||||||
|
* the hash table and return it.
|
||||||
|
*/
|
||||||
|
return MergeSpan (S);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void OpenSpanList (Collection* Spans)
|
||||||
/* Open a list of spans for all existing segments to the given collection of
|
/* 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
|
* spans. The currently active segment will be inserted first with all others
|
||||||
* following.
|
* following.
|
||||||
@ -109,7 +259,7 @@ void OpenSpans (Collection* Spans)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CloseSpans (Collection* Spans)
|
void CloseSpanList (Collection* Spans)
|
||||||
/* Close a list of spans. This will add new segments to the list, mark the end
|
/* 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.
|
* of existing ones, and remove empty spans from the list.
|
||||||
*/
|
*/
|
||||||
@ -141,7 +291,9 @@ void CloseSpans (Collection* Spans)
|
|||||||
} else {
|
} else {
|
||||||
/* Span is not empty */
|
/* Span is not empty */
|
||||||
S->End = S->Seg->PC;
|
S->End = S->Seg->PC;
|
||||||
CollReplace (Spans, S, J++);
|
|
||||||
|
/* Merge duplicate spans, then insert it at the new position */
|
||||||
|
CollReplace (Spans, MergeSpan (S), J++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,37 +303,96 @@ void CloseSpans (Collection* Spans)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void WriteSpan (const Span* S)
|
void WriteSpanList (const Collection* Spans)
|
||||||
/* Write one span to the output file */
|
/* Write a list of spans to the output file */
|
||||||
{
|
{
|
||||||
/* Done accept empty spans */
|
unsigned I;
|
||||||
|
|
||||||
|
/* We only write spans if debug info is enabled */
|
||||||
|
if (DbgSyms == 0) {
|
||||||
|
/* Number of spans is zero */
|
||||||
|
ObjWriteVar (0);
|
||||||
|
} else {
|
||||||
|
/* Write the number of spans */
|
||||||
|
ObjWriteVar (CollCount (Spans));
|
||||||
|
|
||||||
|
/* Write the spans */
|
||||||
|
for (I = 0; I < CollCount (Spans); ++I) {
|
||||||
|
/* Write the id of the next span */
|
||||||
|
ObjWriteVar (((const Span*)CollConstAt (Spans, I))->Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int CollectSpans (void* Entry, void* Data)
|
||||||
|
/* Collect all spans in a collection sorted by id */
|
||||||
|
{
|
||||||
|
/* Cast the pointers to real objects */
|
||||||
|
Span* S = Entry;
|
||||||
|
Collection* C = Data;
|
||||||
|
|
||||||
|
/* Place the entry into the collection */
|
||||||
|
CollReplaceExpand (C, S, S->Id);
|
||||||
|
|
||||||
|
/* Keep the span */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void WriteSpans (void)
|
||||||
|
/* Write all spans to the object file */
|
||||||
|
{
|
||||||
|
/* Tell the object file module that we're about to start the spans */
|
||||||
|
ObjStartSpans ();
|
||||||
|
|
||||||
|
/* We will write scopes only if debug symbols are requested */
|
||||||
|
if (DbgSyms) {
|
||||||
|
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* We must first collect all items in a collection sorted by id */
|
||||||
|
Collection SpanList = STATIC_COLLECTION_INITIALIZER;
|
||||||
|
CollGrow (&SpanList, HT_GetCount (&SpanTab));
|
||||||
|
|
||||||
|
/* Walk over the hash table and fill the span list */
|
||||||
|
HT_Walk (&SpanTab, CollectSpans, &SpanList);
|
||||||
|
|
||||||
|
/* Write the span count to the file */
|
||||||
|
ObjWriteVar (CollCount (&SpanList));
|
||||||
|
|
||||||
|
/* Write all spans */
|
||||||
|
for (I = 0; I < CollCount (&SpanList); ++I) {
|
||||||
|
|
||||||
|
/* Get the span and check it */
|
||||||
|
const Span* S = CollAtUnchecked (&SpanList, I);
|
||||||
CHECK (S->End > S->Start);
|
CHECK (S->End > S->Start);
|
||||||
|
|
||||||
/* Write data for the span We will write the size instead of the end
|
/* Write data for the span We will write the size instead of the
|
||||||
* offset to save some bytes, since most spans are expected to be
|
* end offset to save some bytes, since most spans are expected
|
||||||
* rather small.
|
* to be rather small.
|
||||||
*/
|
*/
|
||||||
ObjWriteVar (S->Seg->Num);
|
ObjWriteVar (S->Seg->Num);
|
||||||
ObjWriteVar (S->Start);
|
ObjWriteVar (S->Start);
|
||||||
ObjWriteVar (S->End - S->Start);
|
ObjWriteVar (S->End - S->Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Free the collection with the spans */
|
||||||
|
DoneCollection (&SpanList);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
void WriteSpans (const Collection* Spans)
|
/* No debug info requested */
|
||||||
/* Write a list of spans to the output file */
|
ObjWriteVar (0);
|
||||||
{
|
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Write the number of spans */
|
|
||||||
ObjWriteVar (CollCount (Spans));
|
|
||||||
|
|
||||||
/* Write the spans */
|
|
||||||
for (I = 0; I < CollCount (Spans); ++I) {
|
|
||||||
/* Write the next span */
|
|
||||||
WriteSpan (CollConstAt (Spans, I));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Done writing the spans */
|
||||||
|
ObjEndSpans ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@
|
|||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
|
#include "gentype.h"
|
||||||
|
#include "hashtab.h"
|
||||||
#include "inline.h"
|
#include "inline.h"
|
||||||
|
|
||||||
|
|
||||||
@ -56,9 +58,12 @@ struct Segment;
|
|||||||
/* Span definition */
|
/* Span definition */
|
||||||
typedef struct Span Span;
|
typedef struct Span Span;
|
||||||
struct Span{
|
struct Span{
|
||||||
|
HashNode Node; /* Node for hash table */
|
||||||
|
unsigned Id; /* Id of span */
|
||||||
struct Segment* Seg; /* Pointer to segment */
|
struct Segment* Seg; /* Pointer to segment */
|
||||||
unsigned long Start; /* Start of range */
|
unsigned Start; /* Start of range */
|
||||||
unsigned long End; /* End of range */
|
unsigned End; /* End of range */
|
||||||
|
unsigned Type; /* Type of data in span */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -79,18 +84,30 @@ INLINE unsigned long GetSpanSize (const Span* R)
|
|||||||
# define GetSpanSize(R) ((R)->End - (R)->Start)
|
# define GetSpanSize(R) ((R)->End - (R)->Start)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void OpenSpans (Collection* Spans);
|
Span* OpenSpan (void);
|
||||||
|
/* Open a span for the active segment and return it. */
|
||||||
|
|
||||||
|
Span* CloseSpan (Span* S);
|
||||||
|
/* Close the given span. Be sure to replace the passed span by the one
|
||||||
|
* returned, since the span will get deleted if it is empty or may be
|
||||||
|
* replaced if a duplicate exists.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void OpenSpanList (Collection* Spans);
|
||||||
/* Open a list of spans for all existing segments to the given collection of
|
/* 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
|
* spans. The currently active segment will be inserted first with all others
|
||||||
* following.
|
* following.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void CloseSpans (Collection* Spans);
|
void CloseSpanList (Collection* Spans);
|
||||||
/* Close all open spans by setting PC to the current PC for the segment. */
|
/* Close all open spans by setting PC to the current PC for the segment. */
|
||||||
|
|
||||||
void WriteSpans (const Collection* Spans);
|
void WriteSpanList (const Collection* Spans);
|
||||||
/* Write a list of spans to the output file */
|
/* Write a list of spans to the output file */
|
||||||
|
|
||||||
|
void WriteSpans (void);
|
||||||
|
/* Write all spans to the object file */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of span.h */
|
/* End of span.h */
|
||||||
|
@ -235,7 +235,7 @@ void SymEnterLevel (const StrBuf* ScopeName, unsigned char Type,
|
|||||||
* space in any segment).
|
* space in any segment).
|
||||||
*/
|
*/
|
||||||
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
|
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
|
||||||
OpenSpans (&CurrentScope->Spans);
|
OpenSpanList (&CurrentScope->Spans);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ void SymLeaveLevel (void)
|
|||||||
* open the spans.
|
* open the spans.
|
||||||
*/
|
*/
|
||||||
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
|
if (CurrentScope->Type <= SCOPE_HAS_DATA) {
|
||||||
CloseSpans (&CurrentScope->Spans);
|
CloseSpanList (&CurrentScope->Spans);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we have spans, the first one is the segment that was active, when the
|
/* If we have spans, the first one is the segment that was active, when the
|
||||||
@ -983,7 +983,7 @@ void WriteScopes (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Spans for this scope */
|
/* Spans for this scope */
|
||||||
WriteSpans (&S->Spans);
|
WriteSpanList (&S->Spans);
|
||||||
|
|
||||||
/* Next scope */
|
/* Next scope */
|
||||||
S = S->Next;
|
S = S->Next;
|
||||||
|
@ -46,10 +46,10 @@
|
|||||||
|
|
||||||
/* Defines for magic and version */
|
/* Defines for magic and version */
|
||||||
#define OBJ_MAGIC 0x616E7A55
|
#define OBJ_MAGIC 0x616E7A55
|
||||||
#define OBJ_VERSION 0x000E
|
#define OBJ_VERSION 0x000F
|
||||||
|
|
||||||
/* Size of an object file header */
|
/* Size of an object file header */
|
||||||
#define OBJ_HDR_SIZE (22*4)
|
#define OBJ_HDR_SIZE (24*4)
|
||||||
|
|
||||||
/* Flag bits */
|
/* Flag bits */
|
||||||
#define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */
|
#define OBJ_FLAGS_DBGINFO 0x0001 /* File has debug info */
|
||||||
@ -83,6 +83,8 @@ struct ObjHeader {
|
|||||||
unsigned long AssertSize; /* 32: Size of assertion table */
|
unsigned long AssertSize; /* 32: Size of assertion table */
|
||||||
unsigned long ScopeOffs; /* 32: Offset into scope table */
|
unsigned long ScopeOffs; /* 32: Offset into scope table */
|
||||||
unsigned long ScopeSize; /* 32: Size of scope table */
|
unsigned long ScopeSize; /* 32: Size of scope table */
|
||||||
|
unsigned long SpanOffs; /* 32: Offset into span table */
|
||||||
|
unsigned long SpanSize; /* 32: Size of span table */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,6 +200,8 @@ static void LibReadObjHeader (Library* L, ObjData* O)
|
|||||||
O->Header.AssertSize = Read32 (L->F);
|
O->Header.AssertSize = Read32 (L->F);
|
||||||
O->Header.ScopeOffs = Read32 (L->F);
|
O->Header.ScopeOffs = Read32 (L->F);
|
||||||
O->Header.ScopeSize = Read32 (L->F);
|
O->Header.ScopeSize = Read32 (L->F);
|
||||||
|
O->Header.SpanOffs = Read32 (L->F);
|
||||||
|
O->Header.SpanSize = Read32 (L->F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -243,6 +245,9 @@ static void ReadBasicData (Library* L, ObjData* O)
|
|||||||
/* Read the files list */
|
/* Read the files list */
|
||||||
ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
|
ObjReadFiles (L->F, O->Start + O->Header.FileOffs, O);
|
||||||
|
|
||||||
|
/* Read the spans */
|
||||||
|
ObjReadSpans (L->F, O->Start + O->Header.SpanOffs, O);
|
||||||
|
|
||||||
/* Read the line infos */
|
/* Read the line infos */
|
||||||
ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
|
ObjReadLineInfos (L->F, O->Start + O->Header.LineInfoOffs, O);
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ LineInfo* ReadLineInfo (FILE* F, ObjData* O)
|
|||||||
LI->File = CollAt (&O->Files, ReadVar (F));
|
LI->File = CollAt (&O->Files, ReadVar (F));
|
||||||
LI->Pos.Name = LI->File->Name;
|
LI->Pos.Name = LI->File->Name;
|
||||||
LI->Type = ReadVar (F);
|
LI->Type = ReadVar (F);
|
||||||
ReadSpans (&LI->Spans, F, O);
|
ReadSpanList (&LI->Spans, F, O);
|
||||||
|
|
||||||
/* Return the struct read */
|
/* Return the struct read */
|
||||||
return LI;
|
return LI;
|
||||||
|
@ -107,6 +107,8 @@ static void ObjReadHeader (FILE* Obj, ObjHeader* H, const char* Name)
|
|||||||
H->AssertSize = Read32 (Obj);
|
H->AssertSize = Read32 (Obj);
|
||||||
H->ScopeOffs = Read32 (Obj);
|
H->ScopeOffs = Read32 (Obj);
|
||||||
H->ScopeSize = Read32 (Obj);
|
H->ScopeSize = Read32 (Obj);
|
||||||
|
H->SpanOffs = Read32 (Obj);
|
||||||
|
H->SpanSize = Read32 (Obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -281,6 +283,25 @@ void ObjReadScopes (FILE* F, unsigned long Pos, ObjData* O)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ObjReadSpans (FILE* F, unsigned long Pos, ObjData* O)
|
||||||
|
/* Read the span table from a file at the given offset */
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
unsigned SpanCount;
|
||||||
|
|
||||||
|
/* Seek to the correct position */
|
||||||
|
FileSetPos (F, Pos);
|
||||||
|
|
||||||
|
/* Read the data */
|
||||||
|
SpanCount = ReadVar (F);
|
||||||
|
CollGrow (&O->Spans, SpanCount);
|
||||||
|
for (I = 0; I < SpanCount; ++I) {
|
||||||
|
CollAppend (&O->Spans, ReadSpan (F, O, I));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ObjAdd (FILE* Obj, const char* Name)
|
void ObjAdd (FILE* Obj, const char* Name)
|
||||||
/* Add an object file to the module list */
|
/* Add an object file to the module list */
|
||||||
{
|
{
|
||||||
@ -302,6 +323,9 @@ void ObjAdd (FILE* Obj, const char* Name)
|
|||||||
/* Read the files list from the object file */
|
/* Read the files list from the object file */
|
||||||
ObjReadFiles (Obj, O->Header.FileOffs, O);
|
ObjReadFiles (Obj, O->Header.FileOffs, O);
|
||||||
|
|
||||||
|
/* Read the spans from the object file */
|
||||||
|
ObjReadSpans (Obj, O->Header.SpanOffs, O);
|
||||||
|
|
||||||
/* Read the line infos from the object file */
|
/* Read the line infos from the object file */
|
||||||
ObjReadLineInfos (Obj, O->Header.LineInfoOffs, O);
|
ObjReadLineInfos (Obj, O->Header.LineInfoOffs, O);
|
||||||
|
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||||
/* Römerstraße 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@ -81,6 +81,9 @@ void ObjReadAssertions (FILE* F, unsigned long Pos, ObjData* O);
|
|||||||
void ObjReadScopes (FILE* F, unsigned long Pos, ObjData* O);
|
void ObjReadScopes (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
/* Read the scope table from a file at the given offset */
|
/* Read the scope table from a file at the given offset */
|
||||||
|
|
||||||
|
void ObjReadSpans (FILE* F, unsigned long Pos, ObjData* O);
|
||||||
|
/* Read the span table from a file at the given offset */
|
||||||
|
|
||||||
void ObjAdd (FILE* F, const char* Name);
|
void ObjAdd (FILE* F, const char* Name);
|
||||||
/* Add an object file to the module list */
|
/* Add an object file to the module list */
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ Scope* ReadScope (FILE* F, ObjData* Obj, unsigned Id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Read the spans for this scope */
|
/* Read the spans for this scope */
|
||||||
ReadSpans (&S->Spans, F, Obj);
|
ReadSpanList (&S->Spans, F, Obj);
|
||||||
|
|
||||||
/* Return the new Scope */
|
/* Return the new Scope */
|
||||||
return S;
|
return S;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "attrib.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* ld65 */
|
/* ld65 */
|
||||||
@ -66,41 +67,38 @@ struct Span {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Span* NewSpan (ObjData* Obj, unsigned SecId, unsigned long Offs, unsigned long Size)
|
static Span* NewSpan (unsigned Id, unsigned Sec, unsigned long Offs, unsigned long Size)
|
||||||
/* Create and return a new span */
|
/* Create and return a new span */
|
||||||
{
|
{
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
Span* S = xmalloc (sizeof (*S));
|
Span* S = xmalloc (sizeof (*S));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
S->Id = CollCount (&Obj->Spans);
|
S->Id = Id;
|
||||||
S->Sec = SecId;
|
S->Sec = Sec;
|
||||||
S->Offs = Offs;
|
S->Offs = Offs;
|
||||||
S->Size = Size;
|
S->Size = Size;
|
||||||
|
|
||||||
/* Insert it into the collection of all spans of this object file */
|
|
||||||
CollAppend (&Obj->Spans, S);
|
|
||||||
|
|
||||||
/* Return the result */
|
/* Return the result */
|
||||||
return S;
|
return S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Span* ReadSpan (FILE* F, ObjData* O)
|
Span* ReadSpan (FILE* F, ObjData* O attribute ((unused)), unsigned Id)
|
||||||
/* Read a Span from a file and return it */
|
/* Read a Span from a file and return it */
|
||||||
{
|
{
|
||||||
/* Create a new Span and return it */
|
/* Create a new Span and return it */
|
||||||
unsigned SecId = ReadVar (F);
|
unsigned SecId = ReadVar (F);
|
||||||
unsigned long Offs = ReadVar (F);
|
unsigned long Offs = ReadVar (F);
|
||||||
unsigned Size = ReadVar (F);
|
unsigned Size = ReadVar (F);
|
||||||
return NewSpan (O, SecId, Offs, Size);
|
return NewSpan (Id, SecId, Offs, Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ReadSpans (Collection* Spans, FILE* F, ObjData* O)
|
void ReadSpanList (Collection* Spans, FILE* F, ObjData* O)
|
||||||
/* Read a list of Spans from a file and return it */
|
/* Read a list of span ids from a file and return the spans for the ids */
|
||||||
{
|
{
|
||||||
/* First is number of Spans */
|
/* First is number of Spans */
|
||||||
unsigned Count = ReadVar (F);
|
unsigned Count = ReadVar (F);
|
||||||
@ -110,7 +108,7 @@ void ReadSpans (Collection* Spans, FILE* F, ObjData* O)
|
|||||||
|
|
||||||
/* Read the spans and add them */
|
/* Read the spans and add them */
|
||||||
while (Count--) {
|
while (Count--) {
|
||||||
CollAppend (Spans, ReadSpan (F, O));
|
CollAppend (Spans, CollAt (&O->Spans, ReadVar (F)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,15 +73,11 @@ typedef struct Span Span;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Span* NewSpan (struct ObjData* Obj, unsigned SecId, unsigned long Offs,
|
Span* ReadSpan (FILE* F, struct ObjData* O, unsigned Id);
|
||||||
unsigned long Size);
|
|
||||||
/* Create and return a new span */
|
|
||||||
|
|
||||||
Span* ReadSpan (FILE* F, struct ObjData* O);
|
|
||||||
/* Read a Span from a file and return it */
|
/* Read a Span from a file and return it */
|
||||||
|
|
||||||
void ReadSpans (Collection* Spans, FILE* F, struct ObjData* O);
|
void ReadSpanList (Collection* Spans, FILE* F, struct ObjData* O);
|
||||||
/* Read a list of Spans from a file and return it */
|
/* Read a list of span ids from a file and return the spans for the ids */
|
||||||
|
|
||||||
void FreeSpan (Span* S);
|
void FreeSpan (Span* S);
|
||||||
/* Free a span structure */
|
/* Free a span structure */
|
||||||
|
@ -136,6 +136,20 @@ static void SkipLineInfoList (FILE* F)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void SkipSpanList (FILE* F)
|
||||||
|
/* Skip a span list from the given file */
|
||||||
|
{
|
||||||
|
/* Count preceeds the list */
|
||||||
|
unsigned long Count = ReadVar (F);
|
||||||
|
|
||||||
|
/* Skip indices */
|
||||||
|
while (Count--) {
|
||||||
|
(void) ReadVar (F);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void SkipExpr (FILE* F)
|
static void SkipExpr (FILE* F)
|
||||||
/* Skip an expression from the given file */
|
/* Skip an expression from the given file */
|
||||||
{
|
{
|
||||||
@ -772,13 +786,17 @@ void DumpObjLineInfo (FILE* F, unsigned long Offset)
|
|||||||
for (I = 0; I < Count; ++I) {
|
for (I = 0; I < Count; ++I) {
|
||||||
|
|
||||||
FilePos Pos;
|
FilePos Pos;
|
||||||
|
unsigned Type;
|
||||||
/* Type of line info */
|
|
||||||
unsigned Type = ReadVar (F);
|
|
||||||
|
|
||||||
/* File position of line info */
|
/* File position of line info */
|
||||||
ReadFilePos (F, &Pos);
|
ReadFilePos (F, &Pos);
|
||||||
|
|
||||||
|
/* Type of line info */
|
||||||
|
Type = ReadVar (F);
|
||||||
|
|
||||||
|
/* Skip the spans */
|
||||||
|
SkipSpanList (F);
|
||||||
|
|
||||||
/* Print the header */
|
/* Print the header */
|
||||||
printf (" Index:%27u\n", I);
|
printf (" Index:%27u\n", I);
|
||||||
|
|
||||||
@ -834,8 +852,6 @@ void DumpObjScopes (FILE* F, unsigned long Offset)
|
|||||||
|
|
||||||
const char* Name;
|
const char* Name;
|
||||||
unsigned Len;
|
unsigned Len;
|
||||||
unsigned SpanCount;
|
|
||||||
unsigned J;
|
|
||||||
|
|
||||||
/* Read the data */
|
/* Read the data */
|
||||||
unsigned ParentId = ReadVar (F);
|
unsigned ParentId = ReadVar (F);
|
||||||
@ -869,17 +885,8 @@ void DumpObjScopes (FILE* F, unsigned long Offset)
|
|||||||
printf (" Label id:%22u\n", LabelId);
|
printf (" Label id:%22u\n", LabelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Spans */
|
/* Skip the spans */
|
||||||
SpanCount = ReadVar (F);
|
SkipSpanList (F);
|
||||||
printf (" Segment spans:\n");
|
|
||||||
printf (" Count:%23u\n", SpanCount);
|
|
||||||
|
|
||||||
for (J = 0; J < SpanCount; ++J) {
|
|
||||||
printf (" Index:%23u\n", J);
|
|
||||||
printf (" Segment:%19lu\n", ReadVar (F));
|
|
||||||
printf (" Start:%13s0x%06lX\n", "", ReadVar (F));
|
|
||||||
printf (" Size:%14s0x%06lX\n", "", ReadVar (F));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Destroy the string pool */
|
/* Destroy the string pool */
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2003 Ullrich von Bassewitz */
|
/* (C) 1998-2011, Ullrich von Bassewitz */
|
||||||
/* Römerstraße 52 */
|
/* Roemerstrasse 52 */
|
||||||
/* D-70794 Filderstadt */
|
/* D-70794 Filderstadt */
|
||||||
/* EMail: uz@cc65.org */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
@ -229,6 +229,8 @@ void ReadObjHeader (FILE* F, ObjHeader* H)
|
|||||||
H->AssertSize = Read32 (F);
|
H->AssertSize = Read32 (F);
|
||||||
H->ScopeOffs = Read32 (F);
|
H->ScopeOffs = Read32 (F);
|
||||||
H->ScopeSize = Read32 (F);
|
H->ScopeSize = Read32 (F);
|
||||||
|
H->SpanOffs = Read32 (F);
|
||||||
|
H->SpanSize = Read32 (F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user