X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=aa0251c389a2329e8065c2942246fb0366fba04b;hb=697abf3ed78b97ef735b0dffbdee88b74eca03cf;hp=17976e52d804514084187442744e32bd99fc623b;hpb=5ee8618510eacaca1f779612103bf709f59e9450;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 17976e52d..aa0251c38 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -48,6 +48,7 @@ #include "error.h" #include "expr.h" #include "fileio.h" +#include "fragment.h" #include "global.h" #include "segments.h" @@ -59,20 +60,6 @@ -/* Fragment structure */ -typedef struct Fragment_ Fragment; -struct Fragment_ { - Fragment* Next; /* Next fragment in list */ - ObjData* Obj; /* Source of fragment */ - unsigned long Size; /* Size of data/expression */ - ExprNode* Expr; /* Expression if FRAG_EXPR */ - FilePos Pos; /* File position in source */ - unsigned char Type; /* Type of fragment */ - unsigned char LitBuf [1]; /* Dynamically alloc'ed literal buffer */ -}; - - - /* Hash table */ #define HASHTAB_SIZE 253 static Segment* HashTab [HASHTAB_SIZE]; @@ -88,36 +75,26 @@ static Segment* SegRoot = 0; /* List of all segments */ -static Fragment* NewFragment (unsigned char Type, unsigned long Size, Section* S) -/* Create a new fragment and insert it into the segment S */ +static Segment* SegFindInternal (const char* Name, unsigned HashVal) +/* Try to find the segment with the given name, return a pointer to the + * segment structure, or 0 if not found. + */ { - /* Allocate memory */ - Fragment* F = xmalloc (sizeof (Fragment) - 1 + Size); /* Portable? */ - - /* Initialize the data */ - F->Next = 0; - F->Obj = 0; - F->Size = Size; - F->Expr = 0; - F->Type = Type; - - /* Insert the code fragment into the segment */ - if (S->FragRoot == 0) { - /* First fragment */ - S->FragRoot = F; - } else { - S->FragLast->Next = F; + Segment* S = HashTab [HashVal]; + while (S) { + if (strcmp (Name, S->Name) == 0) { + /* Found */ + break; + } + S = S->Next; } - S->FragLast = F; - S->Size += Size; - - /* Return the new fragment */ - return F; + /* Not found */ + return S; } -static Segment* NewSegment (const char* Name, unsigned char Type) +static Segment* NewSegment (const char* Name, unsigned HashVal, unsigned char Type) /* Create a new segment and initialize it */ { /* Get the length of the symbol name */ @@ -145,13 +122,50 @@ static Segment* NewSegment (const char* Name, unsigned char Type) SegRoot = S; ++SegCount; + /* Insert the segment into the segment hash list */ + S->Next = HashTab [HashVal]; + HashTab [HashVal] = S; + /* Return the new entry */ return S; } -static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) +Segment* GetSegment (const char* Name, unsigned char Type, const char* ObjName) +/* Search for a segment and return an existing one. If the segment does not + * exist, create a new one and return that. ObjName is only used for the error + * message and may be NULL if the segment is linker generated. + */ +{ + /* Create a hash over the name and try to locate the segment in the table */ + unsigned HashVal = HashStr (Name) % HASHTAB_SIZE; + Segment* S = SegFindInternal (Name, HashVal); + + /* If we don't have that segment already, allocate it using the type of + * the first section. + */ + if (S == 0) { + /* Create a new segment */ + S = NewSegment (Name, HashVal, Type); + } else { + /* Check if the existing segment has the requested type */ + if (S->Type != Type) { + /* Allow an empty object name */ + if (ObjName == 0) { + ObjName = "[linker generated]"; + } + Error ("Module `%s': Type mismatch for segment `%s'", ObjName, Name); + } + } + + /* Return the segment */ + return S; +} + + + +Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Type) /* Create a new section for the given segment */ { unsigned long V; @@ -165,7 +179,7 @@ static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Typ S->Seg = Seg; S->FragRoot = 0; S->FragLast = 0; - S->Size = 0; + S->Size = 0; S->Align = Align; S->Type = Type; @@ -192,30 +206,10 @@ static Section* NewSection (Segment* Seg, unsigned char Align, unsigned char Typ -static Segment* SegFindInternal (const char* Name, unsigned HashVal) -/* Try to find the segment with the given name, return a pointer to the - * segment structure, or 0 if not found. - */ -{ - Segment* S = HashTab [HashVal]; - while (S) { - if (strcmp (Name, S->Name) == 0) { - /* Found */ - break; - } - S = S->Next; - } - /* Not found */ - return S; -} - - - Section* ReadSection (FILE* F, ObjData* O) /* Read a section from a file */ { - unsigned HashVal; - char Name [256]; + char* Name; unsigned long Size; unsigned char Align; unsigned char Type; @@ -223,7 +217,7 @@ Section* ReadSection (FILE* F, ObjData* O) Section* Sec; /* Read the name */ - ReadStr (F, Name); + Name = ReadStr (F); /* Read the size */ Size = Read32 (F); @@ -237,32 +231,18 @@ Section* ReadSection (FILE* F, ObjData* O) /* Print some data */ if (Verbose > 1) { printf ("Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", - O->Name, Name, Size, Align, Type); + GetObjFileName (O), Name, Size, Align, Type); } - /* Create a hash over the name and try to locate the segment in the table */ - HashVal = HashStr (Name) % HASHTAB_SIZE; - S = SegFindInternal (Name, HashVal); + /* Get the segment for this section */ + S = GetSegment (Name, Type, GetObjFileName (O)); - /* If we don't have that segment already, allocate it using the type of - * the first section. - */ - if (S == 0) { - /* Create a new segment and insert it */ - S = NewSegment (Name, Type); - S->Next = HashTab [HashVal]; - HashTab [HashVal] = S; - } + /* We have the segment and don't need the name any longer */ + xfree (Name); /* Allocate the section we will return later */ Sec = NewSection (S, Align, Type); - /* Check if the section has the same type as the segment */ - if (Sec->Type != S->Type) { - /* OOPS */ - Error ("Module `%s': Type mismatch for segment `%s'", O->Name, S->Name); - } - /* Set up the minimum segment alignment */ if (Sec->Align > S->Align) { /* Section needs larger alignment, use this one */ @@ -281,20 +261,8 @@ Section* ReadSection (FILE* F, ObjData* O) /* Handle the different fragment types */ switch (Type) { - case FRAG_LITERAL8: - Frag = NewFragment (FRAG_LITERAL, Read8 (F), Sec); - break; - - case FRAG_LITERAL16: - Frag = NewFragment (FRAG_LITERAL, Read16 (F), Sec); - break; - - case FRAG_LITERAL24: - Frag = NewFragment (FRAG_LITERAL, Read24 (F), Sec); - break; - - case FRAG_LITERAL32: - Frag = NewFragment (FRAG_LITERAL, Read32 (F), Sec); + case FRAG_LITERAL: + Frag = NewFragment (Type, ReadVar (F), Sec); break; case FRAG_EXPR8: @@ -310,12 +278,12 @@ Section* ReadSection (FILE* F, ObjData* O) case FRAG_FILL: /* Will allocate memory, but we don't care... */ - Frag = NewFragment (FRAG_FILL, Read16 (F), Sec); + Frag = NewFragment (Type, ReadVar (F), Sec); break; default: Error ("Unknown fragment type in module `%s', segment `%s': %02X", - O->Name, S->Name, Type); + GetObjFileName (O), S->Name, Type); /* NOTREACHED */ return 0; } @@ -347,9 +315,6 @@ Section* ReadSection (FILE* F, ObjData* O) Size -= Frag->Size; } - /* Increment the segment size by the section size */ - S->Size += Sec->Size; - /* Return the section */ return Sec; } @@ -422,7 +387,7 @@ void SegDump (void) while (Count--) { if (I > 75) { printf ("\n "); - I = 3; + I = 3; } printf (" %02X", *Data++); I += 3; @@ -444,7 +409,7 @@ void SegDump (void) case FRAG_FILL: printf (" Empty space (%lu bytes)\n", F->Size); - break; + break; default: Internal ("Invalid fragment type: %02X", F->Type); @@ -540,12 +505,14 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) case SEG_EXPR_RANGE_ERROR: Error ("Range error in module `%s', line %lu", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + GetSourceFileName (Frag->Obj, Frag->Pos.Name), + Frag->Pos.Line); break; case SEG_EXPR_TOO_COMPLEX: Error ("Expression too complex in module `%s', line %lu", - Frag->Obj->Files [Frag->Pos.Name], Frag->Pos.Line); + GetSourceFileName (Frag->Obj, Frag->Pos.Name), + Frag->Pos.Line); break; default: