From 04d2a349af34a02d124016b9c875e49ba53891da Mon Sep 17 00:00:00 2001 From: cuz Date: Sun, 21 Mar 2004 16:15:55 +0000 Subject: [PATCH] Rewrite. This fixes a bug where a forward reference (+1) to a non existing label caused an internal error. It does also add checking for unreferenced labels. git-svn-id: svn://svn.cc65.org/cc65/trunk@2950 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/ca65/ulabel.c | 163 +++++++++++++++++++--------------------------- 1 file changed, 68 insertions(+), 95 deletions(-) diff --git a/src/ca65/ulabel.c b/src/ca65/ulabel.c index ee20d51db..c997d9b49 100644 --- a/src/ca65/ulabel.c +++ b/src/ca65/ulabel.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2000-2003 Ullrich von Bassewitz */ +/* (C) 2000-2004 Ullrich von Bassewitz */ /* Römerstraße 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ @@ -35,6 +35,7 @@ /* common */ #include "check.h" +#include "coll.h" #include "filepos.h" #include "xmalloc.h" @@ -47,7 +48,7 @@ /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ @@ -55,19 +56,14 @@ /* Struct that describes an unnamed label */ typedef struct ULabel ULabel; struct ULabel { - ULabel* Prev; /* Pointer to previous node in list */ - ULabel* Next; /* Pointer to next node in list */ - FilePos Pos; /* Position of the label in the source */ + FilePos Pos; /* Position of the label in the source */ ExprNode* Val; /* The label value - may be NULL */ + unsigned Ref; /* Number of references */ }; /* List management */ -static ULabel* ULabRoot = 0; /* Root of the list */ -static ULabel* ULabLast = 0; /* Last ULabel */ -static ULabel* ULabLastDef = 0; /* Last defined ULabel */ -static unsigned ULabCount = 0; /* Number of labels */ +static Collection ULabList = STATIC_COLLECTION_INITIALIZER; static unsigned ULabDefCount = 0; /* Number of defined labels */ -static ULabel** ULabList = 0; /* Array with pointers to all labels */ @@ -78,8 +74,8 @@ static ULabel** ULabList = 0; /* Array with pointers to all labels */ static ULabel* NewULabel (ExprNode* Val) -/* Create a new ULabel and insert it into the list. The function will move - * ULabLast, but not ULabLastDef. The created label structure is returned. +/* Create a new ULabel and insert it into the collection. The created label + * structure is returned. */ { /* Allocate memory for the ULabel structure */ @@ -88,21 +84,10 @@ static ULabel* NewULabel (ExprNode* Val) /* Initialize the fields */ L->Pos = CurPos; L->Val = Val; + L->Ref = 0; - /* Insert the label into the list */ - L->Next = 0; - if (ULabRoot == 0) { - /* First label */ - L->Prev = 0; - ULabRoot = L; - } else { - ULabLast->Next = L; - L->Prev = ULabLast; - } - ULabLast = L; - - /* One label more */ - ++ULabCount; + /* Insert the label into the collection */ + CollAppend (&ULabList, L); /* Return the created label */ return L; @@ -118,39 +103,39 @@ ExprNode* ULabRef (int Which) * must be resolved later. */ { + int Index; ULabel* L; /* Which can never be 0 */ PRECONDITION (Which != 0); - /* Which is never really big (usually -3..+3), so a linear search is - * the best we can do here. + /* Get the index of the referenced label */ + if (Which > 0) { + --Which; + } + Index = (int) CollCount (&ULabList) + Which; + + /* We cannot have negative label indices */ + if (Index < 0) { + /* Label does not exist */ + Error ("Undefined label"); + /* We must return something valid */ + return GenCurrentPC(); + } + + /* If the label does already exist, return it's value, otherwise create + * enough forward references, and return a label reference. */ - L = ULabLastDef; - if (Which < 0) { - /* Backward reference */ - while (Which < -1 && L != 0) { - L = L->Prev; - ++Which; - } - if (L == 0) { - /* Label does not exist */ - Error ("Undefined label"); - /* We must return something valid */ - return GenCurrentPC(); - } else { - /* Return a copy of the label value */ - return CloneExpr (L->Val); - } + if (Index < (int) CollCount (&ULabList)) { + L = CollAtUnchecked (&ULabList, Index); + ++L->Ref; + return CloneExpr (L->Val); } else { - /* Forward reference. Create labels as needed */ - unsigned LabelNum = ULabDefCount + Which - 1; - while (LabelNum < ULabCount) { - NewULabel (0); + while (Index >= (int) CollCount (&ULabList)) { + L = NewULabel (0); } - - /* Return an unnamed label expression */ - return GenULabelExpr (LabelNum); + ++L->Ref; + return GenULabelExpr (Index); } } @@ -159,16 +144,21 @@ ExprNode* ULabRef (int Which) void ULabDef (void) /* Define an unnamed label at the current PC */ { - /* Create a new label if needed, or use an existing one */ - if (ULabLastDef == 0 || ULabLastDef->Next == 0) { - /* The last label is also the last defined label, we need a new one */ - ULabLastDef = NewULabel (GenCurrentPC ()); + if (ULabDefCount < CollCount (&ULabList)) { + /* We did already have a forward reference to this label, so has + * already been generated, but doesn't have a value. Use the current + * PC for the label value. + */ + ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount); + CHECK (L->Val == 0); + L->Val = GenCurrentPC (); + L->Pos = CurPos; } else { - /* We do already have the label, but it's undefined until now */ - ULabLastDef = ULabLastDef->Next; - ULabLastDef->Val = GenCurrentPC (); - ULabLastDef->Pos = CurPos; + /* There is no such label, create it */ + NewULabel (GenCurrentPC ()); } + + /* We have one more defined label */ ++ULabDefCount; } @@ -177,8 +167,8 @@ void ULabDef (void) int ULabCanResolve (void) /* Return true if we can resolve arbitrary ULabels. */ { - /* We can resolve labels if we have built the necessary access array */ - return (ULabList != 0); + /* We can resolve labels if we don't have any undefineds */ + return (ULabDefCount == CollCount (&ULabList)); } @@ -189,20 +179,12 @@ ExprNode* ULabResolve (unsigned Index) * if a label is still undefined in this phase. */ { - ULabel* L; + /* Get the label and check that it is defined */ + ULabel* L = CollAt (&ULabList, Index); + CHECK (L->Val != 0); - /* Must be in resolve phase and the index must be valid */ - CHECK (ULabList != 0 && Index < ULabCount); - - /* Get the label */ - L = ULabList [Index]; - - /* If the label is open (not defined), return some valid value */ - if (L->Val == 0) { - return GenLiteralExpr (0); - } else { - return CloneExpr (L->Val); - } + /* Return the label value */ + return CloneExpr (L->Val); } @@ -210,31 +192,22 @@ ExprNode* ULabResolve (unsigned Index) void ULabCheck (void) /* Run through all unnamed labels and check for anomalies and errors */ { - ULabel* L; - /* Check if there are undefined labels */ - if (ULabLastDef) { - L = ULabLastDef->Next; - while (L) { - PError (&L->Pos, "Undefined label"); - L = L->Next; - } + unsigned I = ULabDefCount; + while (I < CollCount (&ULabList)) { + ULabel* L = CollAtUnchecked (&ULabList, I); + PError (&L->Pos, "Undefined label"); + ++I; } - /* Create an array that holds pointers to all labels. This allows us to - * access the labels quickly by index in the resolver phase at the end of - * the assembly. + /* Walk over all labels and emit a warning if any unreferenced ones + * are found. */ - if (ULabCount) { - unsigned I = 0; - ULabList = xmalloc (ULabCount * sizeof (ULabel*)); - L = ULabRoot; - while (L) { - ULabList[I] = L; - ++I; - L = L->Next; - } - CHECK (I == ULabCount); + for (I = 0; I < CollCount (&ULabList); ++I) { + ULabel* L = CollAtUnchecked (&ULabList, I); + if (L->Ref == 0) { + PWarning (&L->Pos, 1, "No reference to unnamed label"); + } } } -- 2.39.5