X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fld65%2Fsegments.c;h=0ae19b6d6398e8db36dd3ca5bf96f884cbf96656;hb=3e887bd9dd06b89177bff864b50fc58c8dadc8bf;hp=7758358180228c2db2bb3f7f46e09f3ff1cc5c0b;hpb=097a01094eedd3b030c2c7a26ddc2ac5067ead28;p=cc65 diff --git a/src/ld65/segments.c b/src/ld65/segments.c index 775835818..0ae19b6d6 100644 --- a/src/ld65/segments.c +++ b/src/ld65/segments.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2000 Ullrich von Bassewitz */ +/* (C) 1998-2001 Ullrich von Bassewitz */ /* Wacholderweg 14 */ /* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -40,6 +40,7 @@ #include "check.h" #include "exprdefs.h" #include "hashstr.h" +#include "print.h" #include "segdefs.h" #include "symdefs.h" #include "xmalloc.h" @@ -48,7 +49,9 @@ #include "error.h" #include "expr.h" #include "fileio.h" +#include "fragment.h" #include "global.h" +#include "lineinfo.h" #include "segments.h" @@ -59,20 +62,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 +77,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 +124,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 +181,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,29 +208,9 @@ 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; unsigned long Size; unsigned char Align; @@ -235,24 +231,11 @@ Section* ReadSection (FILE* F, ObjData* O) Type = Read8 (F); /* 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); - } - - /* Create a hash over the name and try to locate the segment in the table */ - HashVal = HashStr (Name) % HASHTAB_SIZE; - S = SegFindInternal (Name, HashVal); + Print (stdout, 2, "Module `%s': Found segment `%s', size = %lu, align = %u, type = %u\n", + GetObjFileName (O), Name, Size, Align, Type); - /* 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; - } + /* Get the segment for this section */ + S = GetSegment (Name, Type, GetObjFileName (O)); /* We have the segment and don't need the name any longer */ xfree (Name); @@ -260,12 +243,6 @@ Section* ReadSection (FILE* F, ObjData* O) /* 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 */ @@ -277,6 +254,7 @@ Section* ReadSection (FILE* F, ObjData* O) while (Size) { Fragment* Frag; + unsigned LineInfoIndex; /* Read the fragment type */ unsigned char Type = Read8 (F); @@ -306,7 +284,7 @@ Section* ReadSection (FILE* F, ObjData* O) default: Error ("Unknown fragment type in module `%s', segment `%s': %02X", - O->Name, S->Name, Type); + GetObjFileName (O), S->Name, Type); /* NOTREACHED */ return 0; } @@ -323,13 +301,30 @@ Section* ReadSection (FILE* F, ObjData* O) case FRAG_SEXPR: /* An expression */ Frag->Expr = ReadExpr (F, O); - break; + break; } /* Read the file position of the fragment */ ReadFilePos (F, &Frag->Pos); + /* Read the additional line info and resolve it */ + LineInfoIndex = ReadVar (F); + if (LineInfoIndex) { + --LineInfoIndex; + if (LineInfoIndex >= O->LineInfoCount) { + Internal ("In module `%s', file `%s', line %lu: Invalid line " + "info with index %u (max count %u)", + GetObjFileName (O), + GetSourceFileName (O, Frag->Pos.Name), + Frag->Pos.Line, LineInfoIndex, O->LineInfoCount); + } + /* Point from the fragment to the line info... */ + Frag->LI = O->LineInfos[LineInfoIndex]; + /* ...and back from the line info to the fragment */ + CollAppend (&Frag->LI->Fragments, Frag); + } + /* Remember the module we had this fragment from */ Frag->Obj = O; @@ -338,9 +333,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; } @@ -413,7 +405,7 @@ void SegDump (void) while (Count--) { if (I > 75) { printf ("\n "); - I = 3; + I = 3; } printf (" %02X", *Data++); I += 3; @@ -435,7 +427,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); @@ -509,6 +501,7 @@ void SegWrite (FILE* Tgt, Segment* S, SegWriteFunc F, void* Data) /* If we have fill bytes, write them now */ WriteMult (Tgt, S->FillVal, Sec->Fill); + Offs += Sec->Fill; /* Loop over all fragments in this section */ Frag = Sec->FragRoot; @@ -531,12 +524,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: