Add reference counting to line infos. This allows better tracking of the ones

that are actually used.


git-svn-id: svn://svn.cc65.org/cc65/trunk@5212 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
uz
2011-08-18 14:36:38 +00:00
parent bd233ac916
commit 2f9e7d2ca0
11 changed files with 126 additions and 72 deletions

View File

@@ -84,7 +84,7 @@ static Assertion* NewAssertion (ExprNode* Expr, AssertAction Action, unsigned Ms
A->Action = Action; A->Action = Action;
A->Msg = Msg; A->Msg = Msg;
A->LI = EmptyCollection; A->LI = EmptyCollection;
GetFullLineInfo (&A->LI, 1); GetFullLineInfo (&A->LI);
/* Return the new struct */ /* Return the new struct */
return A; return A;

View File

@@ -175,7 +175,7 @@ static IfDesc* AllocIf (const char* Directive, int NeedTerm)
ID->Flags |= ifParentCond; ID->Flags |= ifParentCond;
} }
ID->LineInfos = EmptyCollection; ID->LineInfos = EmptyCollection;
GetFullLineInfo (&ID->LineInfos, 0); GetFullLineInfo (&ID->LineInfos);
ID->Name = Directive; ID->Name = Directive;
/* One more slot allocated */ /* One more slot allocated */
@@ -198,6 +198,7 @@ static void FreeIf (void)
Done = 1; Done = 1;
} else { } else {
Done = (ID->Flags & ifNeedTerm) != 0; Done = (ID->Flags & ifNeedTerm) != 0;
ReleaseFullLineInfo (&ID->LineInfos);
DoneCollection (&ID->LineInfos); DoneCollection (&ID->LineInfos);
--IfCount; --IfCount;
} }
@@ -229,7 +230,8 @@ void DoConditionals (void)
/* Remember the data for the .ELSE */ /* Remember the data for the .ELSE */
if (D) { if (D) {
GetFullLineInfo (&D->LineInfos, 0); ReleaseFullLineInfo (&D->LineInfos);
GetFullLineInfo (&D->LineInfos);
D->Name = ".ELSE"; D->Name = ".ELSE";
} }

View File

@@ -190,7 +190,7 @@ void Warning (unsigned Level, const char* Format, ...)
Collection LineInfos = STATIC_COLLECTION_INITIALIZER; Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
/* Get line infos for the current position */ /* Get line infos for the current position */
GetFullLineInfo (&LineInfos, 0); GetFullLineInfo (&LineInfos);
/* Output the message */ /* Output the message */
va_start (ap, Format); va_start (ap, Format);
@@ -198,6 +198,7 @@ void Warning (unsigned Level, const char* Format, ...)
va_end (ap); va_end (ap);
/* Free the line info list */ /* Free the line info list */
ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos); DoneCollection (&LineInfos);
} }
} }
@@ -265,7 +266,7 @@ void Error (const char* Format, ...)
Collection LineInfos = STATIC_COLLECTION_INITIALIZER; Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
/* Get line infos for the current position */ /* Get line infos for the current position */
GetFullLineInfo (&LineInfos, 0); GetFullLineInfo (&LineInfos);
/* Output the message */ /* Output the message */
va_start (ap, Format); va_start (ap, Format);
@@ -273,6 +274,7 @@ void Error (const char* Format, ...)
va_end (ap); va_end (ap);
/* Free the line info list */ /* Free the line info list */
ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos); DoneCollection (&LineInfos);
} }
@@ -297,7 +299,7 @@ void ErrorSkip (const char* Format, ...)
Collection LineInfos = STATIC_COLLECTION_INITIALIZER; Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
/* Get line infos for the current position */ /* Get line infos for the current position */
GetFullLineInfo (&LineInfos, 0); GetFullLineInfo (&LineInfos);
/* Output the message */ /* Output the message */
va_start (ap, Format); va_start (ap, Format);
@@ -305,6 +307,7 @@ void ErrorSkip (const char* Format, ...)
va_end (ap); va_end (ap);
/* Free the line info list */ /* Free the line info list */
ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos); DoneCollection (&LineInfos);
/* Skip tokens until we reach the end of the line */ /* Skip tokens until we reach the end of the line */

View File

@@ -59,7 +59,7 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len)
F->Next = 0; F->Next = 0;
F->LineList = 0; F->LineList = 0;
F->LI = EmptyCollection; F->LI = EmptyCollection;
GetFullLineInfo (&F->LI, 1); GetFullLineInfo (&F->LI);
F->Len = Len; F->Len = Len;
F->Type = Type; F->Type = Type;

View File

@@ -87,8 +87,7 @@ struct LineInfo {
HashNode Node; /* Hash table node */ HashNode Node; /* Hash table node */
unsigned Id; /* Index */ unsigned Id; /* Index */
LineInfoKey Key; /* Key for this line info */ LineInfoKey Key; /* Key for this line info */
unsigned char Hashed; /* True if in hash list */ unsigned RefCount; /* Reference counter */
unsigned char Referenced; /* Force reference even if no spans */
Collection Spans; /* Segment spans for this line info */ Collection Spans; /* Segment spans for this line info */
Collection OpenSpans; /* List of currently open spans */ Collection OpenSpans; /* List of currently open spans */
}; };
@@ -183,11 +182,13 @@ static LineInfo* NewLineInfo (const LineInfoKey* Key)
InitHashNode (&LI->Node); InitHashNode (&LI->Node);
LI->Id = ~0U; LI->Id = ~0U;
LI->Key = *Key; LI->Key = *Key;
LI->Hashed = 0; LI->RefCount = 0;
LI->Referenced= 0;
InitCollection (&LI->Spans); InitCollection (&LI->Spans);
InitCollection (&LI->OpenSpans); InitCollection (&LI->OpenSpans);
/* Add it to the hash table, so we will find it if necessary */
HT_InsertEntry (&LineInfoTab, LI);
/* Return the new struct */ /* Return the new struct */
return LI; return LI;
} }
@@ -208,22 +209,21 @@ static void FreeLineInfo (LineInfo* LI)
static void RememberLineInfo (LineInfo* LI) static int CheckLineInfo (void* Entry, void* Data attribute ((unused)))
/* Remember a LineInfo by adding it to the hash table and the global list. /* Called from HT_Walk. Remembers used line infos and assigns them an id */
* This will also assign the id which is actually the list position.
*/
{ {
/* Assign the id */ /* Entry is actually a line info */
LI->Id = CollCount (&LineInfoList); LineInfo* LI = Entry;
/* Remember it in the global list */ /* The entry is used if there are spans or the ref counter is non zero */
CollAppend (&LineInfoList, LI); if (LI->RefCount > 0 || CollCount (&LI->Spans) > 0) {
LI->Id = CollCount (&LineInfoList);
/* Add it to the hash table, so we will find it if necessary */ CollAppend (&LineInfoList, LI);
HT_InsertEntry (&LineInfoTab, LI); return 0; /* Keep the entry */
} else {
/* Remember that we have it */ FreeLineInfo (LI);
LI->Hashed = 1; return 1; /* Remove entry from table */
}
} }
@@ -258,6 +258,12 @@ void DoneLineInfo (void)
while (Count) { while (Count) {
EndLine (CollAt (&CurLineInfo, --Count)); EndLine (CollAt (&CurLineInfo, --Count));
} }
/* Walk over the entries in the hash table and sort them into used and
* unused ones. Add the used ones to the line info list and assign them
* an id.
*/
HT_Walk (&LineInfoTab, CheckLineInfo, 0);
} }
@@ -282,18 +288,6 @@ void EndLine (LineInfo* LI)
* line infos. * line infos.
*/ */
CollDeleteItem (&CurLineInfo, LI); CollDeleteItem (&CurLineInfo, LI);
/* If this line info is already hashed, we're done. Otherwise, if it is
* marked as referenced or has non empty spans, remember it. It it is not
* referenced or doesn't have open spans, delete it.
*/
if (!LI->Hashed) {
if (LI->Referenced || CollCount (&LI->Spans) > 0) {
RememberLineInfo (LI);
} else {
FreeLineInfo (LI);
}
}
} }
@@ -353,21 +347,39 @@ void NewAsmLine (void)
void GetFullLineInfo (Collection* LineInfos, int ForceRef) LineInfo* GetAsmLineInfo (void)
/* Return the line info for the current assembler file. The function will
* bump the reference counter before returning the line info.
*/
{
++AsmLineInfo->RefCount;
return AsmLineInfo;
}
void ReleaseLineInfo (LineInfo* LI)
/* Decrease the reference count for a line info */
{
/* Decrease the reference counter */
CHECK (LI->RefCount > 0);
++LI->RefCount;
}
void GetFullLineInfo (Collection* LineInfos)
/* Return full line infos, that is line infos for currently active Slots. The /* Return full line infos, that is line infos for currently active Slots. The
* function will clear LineInfos before usage. If ForceRef is not zero, a * infos will be added to the given collection, existing entries will be left
* forced reference will be added to all line infos, with the consequence that * intact. The reference count of all added entries will be increased.
* they won't get deleted, even if there is no code or data generated for these
* lines.
*/ */
{ {
unsigned I; unsigned I;
/* Clear the collection */ /* If the collection is currently empty, grow it as necessary */
CollDeleteAll (LineInfos); if (CollCount (LineInfos) == 0) {
CollGrow (LineInfos, CollCount (&CurLineInfo));
/* Grow the collection as necessary */ }
CollGrow (LineInfos, CollCount (&CurLineInfo));
/* Copy all valid line infos to the collection */ /* Copy all valid line infos to the collection */
for (I = 0; I < CollCount (&CurLineInfo); ++I) { for (I = 0; I < CollCount (&CurLineInfo); ++I) {
@@ -375,10 +387,8 @@ void GetFullLineInfo (Collection* LineInfos, int ForceRef)
/* Get the line info from the slot */ /* Get the line info from the slot */
LineInfo* LI = CollAt (&CurLineInfo, I); LineInfo* LI = CollAt (&CurLineInfo, I);
/* Mark it as referenced */ /* Bump the reference counter */
if (ForceRef) { ++LI->RefCount;
LI->Referenced = 1;
}
/* Return it to the caller */ /* Return it to the caller */
CollAppend (LineInfos, LI); CollAppend (LineInfos, LI);
@@ -387,6 +397,25 @@ void GetFullLineInfo (Collection* LineInfos, int ForceRef)
void ReleaseFullLineInfo (Collection* LineInfos)
/* Decrease the reference count for a collection full of LineInfos, then clear
* the collection.
*/
{
unsigned I;
/* Walk over all entries */
for (I = 0; I < CollCount (LineInfos); ++I) {
/* Release the the line info */
ReleaseLineInfo (CollAt (LineInfos, I));
}
/* Delete all entries */
CollDeleteAll (LineInfos);
}
const FilePos* GetSourcePos (const LineInfo* LI) const FilePos* GetSourcePos (const LineInfo* LI)
/* Return the source file position from the given line info */ /* Return the source file position from the given line info */
{ {
@@ -417,6 +446,7 @@ void WriteLineInfo (const Collection* LineInfos)
/* Get a pointer to the line info */ /* Get a pointer to the line info */
const LineInfo* LI = CollConstAt (LineInfos, I); const LineInfo* LI = CollConstAt (LineInfos, I);
/* Safety */
CHECK (LI->Id != ~0U); CHECK (LI->Id != ~0U);
/* Write the index to the file */ /* Write the index to the file */

View File

@@ -81,12 +81,23 @@ void NewAsmLine (void);
* changed, end the old and start the new line as necessary. * changed, end the old and start the new line as necessary.
*/ */
void GetFullLineInfo (Collection* LineInfos, int ForceRef); LineInfo* GetAsmLineInfo (void);
/* Return the line info for the current assembler file. The function will
* bump the reference counter before returning the line info.
*/
void ReleaseLineInfo (LineInfo* LI);
/* Decrease the reference count for a line info */
void GetFullLineInfo (Collection* LineInfos);
/* Return full line infos, that is line infos for currently active Slots. The /* Return full line infos, that is line infos for currently active Slots. The
* function will clear LineInfos before usage. If ForceRef is not zero, a * infos will be added to the given collection, existing entries will be left
* forced reference will be added to all line infos, with the consequence that * intact. The reference count of all added entries will be increased.
* they won't get deleted, even if there is no code or data generated for these */
* lines.
void ReleaseFullLineInfo (Collection* LineInfos);
/* Decrease the reference count for a collection full of LineInfos, then clear
* the collection.
*/ */
const FilePos* GetSourcePos (const LineInfo* LI); const FilePos* GetSourcePos (const LineInfo* LI);

View File

@@ -1011,9 +1011,9 @@ int main (int argc, char* argv [])
CheckPseudo (); CheckPseudo ();
} }
/* If we didn't have any errors, check the unnamed labels */ /* If we didn't have any errors, check and cleanup the unnamed labels */
if (ErrorCount == 0) { if (ErrorCount == 0) {
ULabCheck (); ULabDone ();
} }
/* If we didn't have any errors, check the symbol table */ /* If we didn't have any errors, check the symbol table */

View File

@@ -1142,12 +1142,13 @@ CharAgain:
} else if (CComments) { } else if (CComments) {
/* Remember the position, then skip the '*' */ /* Remember the position, then skip the '*' */
Collection LineInfos = STATIC_COLLECTION_INITIALIZER; Collection LineInfos = STATIC_COLLECTION_INITIALIZER;
GetFullLineInfo (&LineInfos, 0); GetFullLineInfo (&LineInfos);
NextChar (); NextChar ();
do { do {
while (C != '*') { while (C != '*') {
if (C == EOF) { if (C == EOF) {
LIError (&LineInfos, "Unterminated comment"); LIError (&LineInfos, "Unterminated comment");
ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos); DoneCollection (&LineInfos);
goto CharAgain; goto CharAgain;
} }
@@ -1156,6 +1157,7 @@ CharAgain:
NextChar (); NextChar ();
} while (C != '/'); } while (C != '/');
NextChar (); NextChar ();
ReleaseFullLineInfo (&LineInfos);
DoneCollection (&LineInfos); DoneCollection (&LineInfos);
goto Again; goto Again;
} }

View File

@@ -87,7 +87,7 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags)
S->Locals = 0; S->Locals = 0;
S->Sym.Tab = 0; S->Sym.Tab = 0;
S->LineInfos = EmptyCollection; S->LineInfos = EmptyCollection;
GetFullLineInfo (&S->LineInfos, 1); GetFullLineInfo (&S->LineInfos);
for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) { for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) {
S->GuessedUse[I] = 0; S->GuessedUse[I] = 0;
} }

View File

@@ -83,7 +83,7 @@ static ULabel* NewULabel (ExprNode* Val)
/* Initialize the fields */ /* Initialize the fields */
L->LineInfos = EmptyCollection; L->LineInfos = EmptyCollection;
GetFullLineInfo (&L->LineInfos, 0); GetFullLineInfo (&L->LineInfos);
L->Val = Val; L->Val = Val;
L->Ref = 0; L->Ref = 0;
@@ -160,8 +160,9 @@ void ULabDef (void)
*/ */
ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount); ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
CHECK (L->Val == 0); CHECK (L->Val == 0);
L->Val = GenCurrentPC (); L->Val = GenCurrentPC ();
GetFullLineInfo (&L->LineInfos, 0); ReleaseFullLineInfo (&L->LineInfos);
GetFullLineInfo (&L->LineInfos);
} else { } else {
/* There is no such label, create it */ /* There is no such label, create it */
NewULabel (GenCurrentPC ()); NewULabel (GenCurrentPC ());
@@ -198,8 +199,10 @@ ExprNode* ULabResolve (unsigned Index)
void ULabCheck (void) void ULabDone (void)
/* Run through all unnamed labels and check for anomalies and errors */ /* Run through all unnamed labels, check for anomalies and errors and do
* necessary cleanups.
*/
{ {
/* Check if there are undefined labels */ /* Check if there are undefined labels */
unsigned I = ULabDefCount; unsigned I = ULabDefCount;
@@ -210,13 +213,14 @@ void ULabCheck (void)
} }
/* Walk over all labels and emit a warning if any unreferenced ones /* Walk over all labels and emit a warning if any unreferenced ones
* are found. * are found. Remove line infos because they're no longer needed.
*/ */
for (I = 0; I < CollCount (&ULabList); ++I) { for (I = 0; I < CollCount (&ULabList); ++I) {
ULabel* L = CollAtUnchecked (&ULabList, I); ULabel* L = CollAtUnchecked (&ULabList, I);
if (L->Ref == 0) { if (L->Ref == 0) {
LIWarning (&L->LineInfos, 1, "No reference to unnamed label"); LIWarning (&L->LineInfos, 1, "No reference to unnamed label");
} }
ReleaseFullLineInfo (&L->LineInfos);
} }
} }

View File

@@ -6,10 +6,10 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000 Ullrich von Bassewitz */ /* (C) 2000-2011, Ullrich von Bassewitz */
/* Wacholderweg 14 */ /* Roemerstrasse 52 */
/* D-70597 Stuttgart */ /* D-70794 Filderstadt */
/* EMail: uz@musoftware.de */ /* EMail: uz@cc65.org */
/* */ /* */
/* */ /* */
/* This software is provided 'as-is', without any expressed or implied */ /* This software is provided 'as-is', without any expressed or implied */
@@ -64,8 +64,10 @@ ExprNode* ULabResolve (unsigned Index);
* if a label is still undefined in this phase. * if a label is still undefined in this phase.
*/ */
void ULabCheck (void); void ULabDone (void);
/* Run through all unnamed labels and check for anomalies and errors */ /* Run through all unnamed labels, check for anomalies and errors and do
* necessary cleanups.
*/