From 2f9e7d2ca05317fc95d6a9e661bf01b9b5a339cb Mon Sep 17 00:00:00 2001 From: uz Date: Thu, 18 Aug 2011 14:36:38 +0000 Subject: [PATCH] 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 --- src/ca65/asserts.c | 2 +- src/ca65/condasm.c | 6 ++- src/ca65/error.c | 9 ++-- src/ca65/fragment.c | 2 +- src/ca65/lineinfo.c | 120 +++++++++++++++++++++++++++----------------- src/ca65/lineinfo.h | 21 ++++++-- src/ca65/main.c | 4 +- src/ca65/scanner.c | 4 +- src/ca65/symentry.c | 2 +- src/ca65/ulabel.c | 16 +++--- src/ca65/ulabel.h | 14 +++--- 11 files changed, 127 insertions(+), 73 deletions(-) diff --git a/src/ca65/asserts.c b/src/ca65/asserts.c index d70f8f602..84b2621c7 100644 --- a/src/ca65/asserts.c +++ b/src/ca65/asserts.c @@ -84,7 +84,7 @@ static Assertion* NewAssertion (ExprNode* Expr, AssertAction Action, unsigned Ms A->Action = Action; A->Msg = Msg; A->LI = EmptyCollection; - GetFullLineInfo (&A->LI, 1); + GetFullLineInfo (&A->LI); /* Return the new struct */ return A; diff --git a/src/ca65/condasm.c b/src/ca65/condasm.c index 274b1a1d9..a14bbc2f6 100644 --- a/src/ca65/condasm.c +++ b/src/ca65/condasm.c @@ -175,7 +175,7 @@ static IfDesc* AllocIf (const char* Directive, int NeedTerm) ID->Flags |= ifParentCond; } ID->LineInfos = EmptyCollection; - GetFullLineInfo (&ID->LineInfos, 0); + GetFullLineInfo (&ID->LineInfos); ID->Name = Directive; /* One more slot allocated */ @@ -198,6 +198,7 @@ static void FreeIf (void) Done = 1; } else { Done = (ID->Flags & ifNeedTerm) != 0; + ReleaseFullLineInfo (&ID->LineInfos); DoneCollection (&ID->LineInfos); --IfCount; } @@ -229,7 +230,8 @@ void DoConditionals (void) /* Remember the data for the .ELSE */ if (D) { - GetFullLineInfo (&D->LineInfos, 0); + ReleaseFullLineInfo (&D->LineInfos); + GetFullLineInfo (&D->LineInfos); D->Name = ".ELSE"; } diff --git a/src/ca65/error.c b/src/ca65/error.c index 7592c4557..85511d107 100644 --- a/src/ca65/error.c +++ b/src/ca65/error.c @@ -190,7 +190,7 @@ void Warning (unsigned Level, const char* Format, ...) Collection LineInfos = STATIC_COLLECTION_INITIALIZER; /* Get line infos for the current position */ - GetFullLineInfo (&LineInfos, 0); + GetFullLineInfo (&LineInfos); /* Output the message */ va_start (ap, Format); @@ -198,6 +198,7 @@ void Warning (unsigned Level, const char* Format, ...) va_end (ap); /* Free the line info list */ + ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); } } @@ -265,7 +266,7 @@ void Error (const char* Format, ...) Collection LineInfos = STATIC_COLLECTION_INITIALIZER; /* Get line infos for the current position */ - GetFullLineInfo (&LineInfos, 0); + GetFullLineInfo (&LineInfos); /* Output the message */ va_start (ap, Format); @@ -273,6 +274,7 @@ void Error (const char* Format, ...) va_end (ap); /* Free the line info list */ + ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); } @@ -297,7 +299,7 @@ void ErrorSkip (const char* Format, ...) Collection LineInfos = STATIC_COLLECTION_INITIALIZER; /* Get line infos for the current position */ - GetFullLineInfo (&LineInfos, 0); + GetFullLineInfo (&LineInfos); /* Output the message */ va_start (ap, Format); @@ -305,6 +307,7 @@ void ErrorSkip (const char* Format, ...) va_end (ap); /* Free the line info list */ + ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); /* Skip tokens until we reach the end of the line */ diff --git a/src/ca65/fragment.c b/src/ca65/fragment.c index 4660490f9..059371e77 100644 --- a/src/ca65/fragment.c +++ b/src/ca65/fragment.c @@ -59,7 +59,7 @@ Fragment* NewFragment (unsigned char Type, unsigned short Len) F->Next = 0; F->LineList = 0; F->LI = EmptyCollection; - GetFullLineInfo (&F->LI, 1); + GetFullLineInfo (&F->LI); F->Len = Len; F->Type = Type; diff --git a/src/ca65/lineinfo.c b/src/ca65/lineinfo.c index ad5cb8f35..cddd17ac3 100644 --- a/src/ca65/lineinfo.c +++ b/src/ca65/lineinfo.c @@ -87,8 +87,7 @@ struct LineInfo { HashNode Node; /* Hash table node */ unsigned Id; /* Index */ LineInfoKey Key; /* Key for this line info */ - unsigned char Hashed; /* True if in hash list */ - unsigned char Referenced; /* Force reference even if no spans */ + unsigned RefCount; /* Reference counter */ Collection Spans; /* Segment spans for this line info */ Collection OpenSpans; /* List of currently open spans */ }; @@ -183,11 +182,13 @@ static LineInfo* NewLineInfo (const LineInfoKey* Key) InitHashNode (&LI->Node); LI->Id = ~0U; LI->Key = *Key; - LI->Hashed = 0; - LI->Referenced= 0; + LI->RefCount = 0; InitCollection (&LI->Spans); 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 LI; } @@ -208,22 +209,21 @@ static void FreeLineInfo (LineInfo* LI) -static void RememberLineInfo (LineInfo* LI) -/* Remember a LineInfo by adding it to the hash table and the global list. - * This will also assign the id which is actually the list position. - */ +static int CheckLineInfo (void* Entry, void* Data attribute ((unused))) +/* Called from HT_Walk. Remembers used line infos and assigns them an id */ { - /* Assign the id */ - LI->Id = CollCount (&LineInfoList); - - /* Remember it in the global list */ - CollAppend (&LineInfoList, LI); - - /* Add it to the hash table, so we will find it if necessary */ - HT_InsertEntry (&LineInfoTab, LI); - - /* Remember that we have it */ - LI->Hashed = 1; + /* Entry is actually a line info */ + LineInfo* LI = Entry; + + /* The entry is used if there are spans or the ref counter is non zero */ + if (LI->RefCount > 0 || CollCount (&LI->Spans) > 0) { + LI->Id = CollCount (&LineInfoList); + CollAppend (&LineInfoList, LI); + return 0; /* Keep the entry */ + } else { + FreeLineInfo (LI); + return 1; /* Remove entry from table */ + } } @@ -258,6 +258,12 @@ void DoneLineInfo (void) while (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. */ 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 - * function will clear LineInfos before usage. If ForceRef is not zero, a - * forced reference will be added to all line infos, with the consequence that - * they won't get deleted, even if there is no code or data generated for these - * lines. + * infos will be added to the given collection, existing entries will be left + * intact. The reference count of all added entries will be increased. */ { unsigned I; - /* Clear the collection */ - CollDeleteAll (LineInfos); - - /* Grow the collection as necessary */ - CollGrow (LineInfos, CollCount (&CurLineInfo)); + /* If the collection is currently empty, grow it as necessary */ + if (CollCount (LineInfos) == 0) { + CollGrow (LineInfos, CollCount (&CurLineInfo)); + } /* Copy all valid line infos to the collection */ for (I = 0; I < CollCount (&CurLineInfo); ++I) { @@ -375,10 +387,8 @@ void GetFullLineInfo (Collection* LineInfos, int ForceRef) /* Get the line info from the slot */ LineInfo* LI = CollAt (&CurLineInfo, I); - /* Mark it as referenced */ - if (ForceRef) { - LI->Referenced = 1; - } + /* Bump the reference counter */ + ++LI->RefCount; /* Return it to the caller */ 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) /* 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 */ const LineInfo* LI = CollConstAt (LineInfos, I); + /* Safety */ CHECK (LI->Id != ~0U); /* Write the index to the file */ diff --git a/src/ca65/lineinfo.h b/src/ca65/lineinfo.h index 17d2dfd43..94b51ae4f 100644 --- a/src/ca65/lineinfo.h +++ b/src/ca65/lineinfo.h @@ -81,12 +81,23 @@ void NewAsmLine (void); * 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 - * function will clear LineInfos before usage. If ForceRef is not zero, a - * forced reference will be added to all line infos, with the consequence that - * they won't get deleted, even if there is no code or data generated for these - * lines. + * infos will be added to the given collection, existing entries will be left + * intact. The reference count of all added entries will be increased. + */ + +void ReleaseFullLineInfo (Collection* LineInfos); +/* Decrease the reference count for a collection full of LineInfos, then clear + * the collection. */ const FilePos* GetSourcePos (const LineInfo* LI); diff --git a/src/ca65/main.c b/src/ca65/main.c index 1104f5b68..17aca8efc 100644 --- a/src/ca65/main.c +++ b/src/ca65/main.c @@ -1011,9 +1011,9 @@ int main (int argc, char* argv []) 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) { - ULabCheck (); + ULabDone (); } /* If we didn't have any errors, check the symbol table */ diff --git a/src/ca65/scanner.c b/src/ca65/scanner.c index bb31799dc..04f217ceb 100644 --- a/src/ca65/scanner.c +++ b/src/ca65/scanner.c @@ -1142,12 +1142,13 @@ CharAgain: } else if (CComments) { /* Remember the position, then skip the '*' */ Collection LineInfos = STATIC_COLLECTION_INITIALIZER; - GetFullLineInfo (&LineInfos, 0); + GetFullLineInfo (&LineInfos); NextChar (); do { while (C != '*') { if (C == EOF) { LIError (&LineInfos, "Unterminated comment"); + ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); goto CharAgain; } @@ -1156,6 +1157,7 @@ CharAgain: NextChar (); } while (C != '/'); NextChar (); + ReleaseFullLineInfo (&LineInfos); DoneCollection (&LineInfos); goto Again; } diff --git a/src/ca65/symentry.c b/src/ca65/symentry.c index d46f21ac0..cb250478b 100644 --- a/src/ca65/symentry.c +++ b/src/ca65/symentry.c @@ -87,7 +87,7 @@ SymEntry* NewSymEntry (const StrBuf* Name, unsigned Flags) S->Locals = 0; S->Sym.Tab = 0; S->LineInfos = EmptyCollection; - GetFullLineInfo (&S->LineInfos, 1); + GetFullLineInfo (&S->LineInfos); for (I = 0; I < sizeof (S->GuessedUse) / sizeof (S->GuessedUse[0]); ++I) { S->GuessedUse[I] = 0; } diff --git a/src/ca65/ulabel.c b/src/ca65/ulabel.c index 023dd1375..768312c19 100644 --- a/src/ca65/ulabel.c +++ b/src/ca65/ulabel.c @@ -83,7 +83,7 @@ static ULabel* NewULabel (ExprNode* Val) /* Initialize the fields */ L->LineInfos = EmptyCollection; - GetFullLineInfo (&L->LineInfos, 0); + GetFullLineInfo (&L->LineInfos); L->Val = Val; L->Ref = 0; @@ -160,8 +160,9 @@ void ULabDef (void) */ ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount); CHECK (L->Val == 0); - L->Val = GenCurrentPC (); - GetFullLineInfo (&L->LineInfos, 0); + L->Val = GenCurrentPC (); + ReleaseFullLineInfo (&L->LineInfos); + GetFullLineInfo (&L->LineInfos); } else { /* There is no such label, create it */ NewULabel (GenCurrentPC ()); @@ -198,8 +199,10 @@ ExprNode* ULabResolve (unsigned Index) -void ULabCheck (void) -/* Run through all unnamed labels and check for anomalies and errors */ +void ULabDone (void) +/* Run through all unnamed labels, check for anomalies and errors and do + * necessary cleanups. + */ { /* Check if there are undefined labels */ unsigned I = ULabDefCount; @@ -210,13 +213,14 @@ void ULabCheck (void) } /* 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) { ULabel* L = CollAtUnchecked (&ULabList, I); if (L->Ref == 0) { LIWarning (&L->LineInfos, 1, "No reference to unnamed label"); } + ReleaseFullLineInfo (&L->LineInfos); } } diff --git a/src/ca65/ulabel.h b/src/ca65/ulabel.h index ea2e46767..9e8d1b37f 100644 --- a/src/ca65/ulabel.h +++ b/src/ca65/ulabel.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2000 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 2000-2011, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* 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. */ -void ULabCheck (void); -/* Run through all unnamed labels and check for anomalies and errors */ +void ULabDone (void); +/* Run through all unnamed labels, check for anomalies and errors and do + * necessary cleanups. + */ -- 2.39.5