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
This commit is contained in:
cuz
2004-03-21 16:15:55 +00:00
parent eeea3b9bc2
commit 04d2a349af

View File

@@ -6,7 +6,7 @@
/* */ /* */
/* */ /* */
/* */ /* */
/* (C) 2000-2003 Ullrich von Bassewitz */ /* (C) 2000-2004 Ullrich von Bassewitz */
/* R<>merstra<72>e 52 */ /* R<>merstra<72>e 52 */
/* D-70794 Filderstadt */ /* D-70794 Filderstadt */
/* EMail: uz@cc65.org */ /* EMail: uz@cc65.org */
@@ -35,6 +35,7 @@
/* common */ /* common */
#include "check.h" #include "check.h"
#include "coll.h"
#include "filepos.h" #include "filepos.h"
#include "xmalloc.h" #include "xmalloc.h"
@@ -55,19 +56,14 @@
/* Struct that describes an unnamed label */ /* Struct that describes an unnamed label */
typedef struct ULabel ULabel; typedef struct ULabel ULabel;
struct 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 */ ExprNode* Val; /* The label value - may be NULL */
unsigned Ref; /* Number of references */
}; };
/* List management */ /* List management */
static ULabel* ULabRoot = 0; /* Root of the list */ static Collection ULabList = STATIC_COLLECTION_INITIALIZER;
static ULabel* ULabLast = 0; /* Last ULabel */
static ULabel* ULabLastDef = 0; /* Last defined ULabel */
static unsigned ULabCount = 0; /* Number of labels */
static unsigned ULabDefCount = 0; /* Number of defined labels */ 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) static ULabel* NewULabel (ExprNode* Val)
/* Create a new ULabel and insert it into the list. The function will move /* Create a new ULabel and insert it into the collection. The created label
* ULabLast, but not ULabLastDef. The created label structure is returned. * structure is returned.
*/ */
{ {
/* Allocate memory for the ULabel structure */ /* Allocate memory for the ULabel structure */
@@ -88,21 +84,10 @@ static ULabel* NewULabel (ExprNode* Val)
/* Initialize the fields */ /* Initialize the fields */
L->Pos = CurPos; L->Pos = CurPos;
L->Val = Val; L->Val = Val;
L->Ref = 0;
/* Insert the label into the list */ /* Insert the label into the collection */
L->Next = 0; CollAppend (&ULabList, L);
if (ULabRoot == 0) {
/* First label */
L->Prev = 0;
ULabRoot = L;
} else {
ULabLast->Next = L;
L->Prev = ULabLast;
}
ULabLast = L;
/* One label more */
++ULabCount;
/* Return the created label */ /* Return the created label */
return L; return L;
@@ -118,39 +103,39 @@ ExprNode* ULabRef (int Which)
* must be resolved later. * must be resolved later.
*/ */
{ {
int Index;
ULabel* L; ULabel* L;
/* Which can never be 0 */ /* Which can never be 0 */
PRECONDITION (Which != 0); PRECONDITION (Which != 0);
/* Which is never really big (usually -3..+3), so a linear search is /* Get the index of the referenced label */
* the best we can do here. if (Which > 0) {
*/ --Which;
L = ULabLastDef;
if (Which < 0) {
/* Backward reference */
while (Which < -1 && L != 0) {
L = L->Prev;
++Which;
} }
if (L == 0) { Index = (int) CollCount (&ULabList) + Which;
/* We cannot have negative label indices */
if (Index < 0) {
/* Label does not exist */ /* Label does not exist */
Error ("Undefined label"); Error ("Undefined label");
/* We must return something valid */ /* We must return something valid */
return GenCurrentPC(); return GenCurrentPC();
} else {
/* Return a copy of the label value */
return CloneExpr (L->Val);
}
} else {
/* Forward reference. Create labels as needed */
unsigned LabelNum = ULabDefCount + Which - 1;
while (LabelNum < ULabCount) {
NewULabel (0);
} }
/* Return an unnamed label expression */ /* If the label does already exist, return it's value, otherwise create
return GenULabelExpr (LabelNum); * enough forward references, and return a label reference.
*/
if (Index < (int) CollCount (&ULabList)) {
L = CollAtUnchecked (&ULabList, Index);
++L->Ref;
return CloneExpr (L->Val);
} else {
while (Index >= (int) CollCount (&ULabList)) {
L = NewULabel (0);
}
++L->Ref;
return GenULabelExpr (Index);
} }
} }
@@ -159,16 +144,21 @@ ExprNode* ULabRef (int Which)
void ULabDef (void) void ULabDef (void)
/* Define an unnamed label at the current PC */ /* Define an unnamed label at the current PC */
{ {
/* Create a new label if needed, or use an existing one */ if (ULabDefCount < CollCount (&ULabList)) {
if (ULabLastDef == 0 || ULabLastDef->Next == 0) { /* We did already have a forward reference to this label, so has
/* The last label is also the last defined label, we need a new one */ * already been generated, but doesn't have a value. Use the current
ULabLastDef = NewULabel (GenCurrentPC ()); * PC for the label value.
*/
ULabel* L = CollAtUnchecked (&ULabList, ULabDefCount);
CHECK (L->Val == 0);
L->Val = GenCurrentPC ();
L->Pos = CurPos;
} else { } else {
/* We do already have the label, but it's undefined until now */ /* There is no such label, create it */
ULabLastDef = ULabLastDef->Next; NewULabel (GenCurrentPC ());
ULabLastDef->Val = GenCurrentPC ();
ULabLastDef->Pos = CurPos;
} }
/* We have one more defined label */
++ULabDefCount; ++ULabDefCount;
} }
@@ -177,8 +167,8 @@ void ULabDef (void)
int ULabCanResolve (void) int ULabCanResolve (void)
/* Return true if we can resolve arbitrary ULabels. */ /* Return true if we can resolve arbitrary ULabels. */
{ {
/* We can resolve labels if we have built the necessary access array */ /* We can resolve labels if we don't have any undefineds */
return (ULabList != 0); return (ULabDefCount == CollCount (&ULabList));
} }
@@ -189,52 +179,35 @@ ExprNode* ULabResolve (unsigned Index)
* if a label is still undefined in this phase. * 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 */ /* Return the label value */
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 CloneExpr (L->Val);
} }
}
void ULabCheck (void) void ULabCheck (void)
/* Run through all unnamed labels and check for anomalies and errors */ /* Run through all unnamed labels and check for anomalies and errors */
{ {
ULabel* L;
/* Check if there are undefined labels */ /* Check if there are undefined labels */
if (ULabLastDef) { unsigned I = ULabDefCount;
L = ULabLastDef->Next; while (I < CollCount (&ULabList)) {
while (L) { ULabel* L = CollAtUnchecked (&ULabList, I);
PError (&L->Pos, "Undefined label"); PError (&L->Pos, "Undefined label");
L = L->Next;
}
}
/* 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.
*/
if (ULabCount) {
unsigned I = 0;
ULabList = xmalloc (ULabCount * sizeof (ULabel*));
L = ULabRoot;
while (L) {
ULabList[I] = L;
++I; ++I;
L = L->Next;
} }
CHECK (I == ULabCount);
/* Walk over all labels and emit a warning if any unreferenced ones
* are found.
*/
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");
}
} }
} }