Cleaned up the code used for handling jump labels and the label name.
Fixed a problem that caused the optimizer not to detect that flags set by a load are used, if the use is "hidden" behind an unconditional branch. This caused the optimizer to remove the load. git-svn-id: svn://svn.cc65.org/cc65/trunk@3111 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -323,6 +323,22 @@ void CE_AttachLabel (CodeEntry* E, CodeLabel* L)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void CE_ClearJumpTo (CodeEntry* E)
|
||||||
|
/* Clear the JumpTo entry and the argument (which contained the name of the
|
||||||
|
* label). Note: The function will not clear the backpointer from the label,
|
||||||
|
* so use it with care.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Clear the JumpTo entry */
|
||||||
|
E->JumpTo = 0;
|
||||||
|
|
||||||
|
/* Clear the argument and assign the empty one */
|
||||||
|
FreeArg (E->Arg);
|
||||||
|
E->Arg = EmptyArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void CE_MoveLabel (CodeLabel* L, CodeEntry* E)
|
void CE_MoveLabel (CodeLabel* L, CodeEntry* E)
|
||||||
/* Move the code label L from it's former owner to the code entry E. */
|
/* Move the code label L from it's former owner to the code entry E. */
|
||||||
{
|
{
|
||||||
@@ -391,6 +407,33 @@ int CE_UseLoadFlags (const CodeEntry* E)
|
|||||||
* a register (N and Z).
|
* a register (N and Z).
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
/* Follow unconditional branches, but beware of endless loops. After this,
|
||||||
|
* E will point to the first entry that is not a branch.
|
||||||
|
*/
|
||||||
|
if (E->Info & OF_UBRA) {
|
||||||
|
Collection C = AUTO_COLLECTION_INITIALIZER;
|
||||||
|
|
||||||
|
/* Follow the chain */
|
||||||
|
while (E->Info & OF_UBRA) {
|
||||||
|
|
||||||
|
/* Remember the entry so we can detect loops */
|
||||||
|
CollAppend (&C, (void*) E);
|
||||||
|
|
||||||
|
/* Check the target */
|
||||||
|
if (E->JumpTo == 0 || CollIndex (&C, E->JumpTo->Owner) >= 0) {
|
||||||
|
/* Unconditional jump to external symbol, or endless loop. */
|
||||||
|
DoneCollection (&C);
|
||||||
|
return 0; /* Flags not used */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Follow the chain */
|
||||||
|
E = E->JumpTo->Owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete the collection */
|
||||||
|
DoneCollection (&C);
|
||||||
|
}
|
||||||
|
|
||||||
/* A branch will use the flags */
|
/* A branch will use the flags */
|
||||||
if (E->Info & OF_FBRA) {
|
if (E->Info & OF_FBRA) {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -429,7 +472,7 @@ void CE_FreeRegInfo (CodeEntry* E)
|
|||||||
/* Free an existing register info struct */
|
/* Free an existing register info struct */
|
||||||
{
|
{
|
||||||
if (E->RI) {
|
if (E->RI) {
|
||||||
FreeRegInfo (E->RI);
|
FreeRegInfo (E->RI);
|
||||||
E->RI = 0;
|
E->RI = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,12 @@ int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2);
|
|||||||
void CE_AttachLabel (CodeEntry* E, CodeLabel* L);
|
void CE_AttachLabel (CodeEntry* E, CodeLabel* L);
|
||||||
/* Attach the label to the entry */
|
/* Attach the label to the entry */
|
||||||
|
|
||||||
|
void CE_ClearJumpTo (CodeEntry* E);
|
||||||
|
/* Clear the JumpTo entry and the argument (which contained the name of the
|
||||||
|
* label). Note: The function will not clear the backpointer from the label,
|
||||||
|
* so use it with care.
|
||||||
|
*/
|
||||||
|
|
||||||
#if defined(HAVE_INLINE)
|
#if defined(HAVE_INLINE)
|
||||||
INLINE int CE_HasLabel (const CodeEntry* E)
|
INLINE int CE_HasLabel (const CodeEntry* E)
|
||||||
/* Check if the given code entry has labels attached */
|
/* Check if the given code entry has labels attached */
|
||||||
|
|||||||
@@ -829,7 +829,7 @@ void CS_DelLabel (CodeSeg* S, CodeLabel* L)
|
|||||||
/* Get the insn referencing this label */
|
/* Get the insn referencing this label */
|
||||||
CodeEntry* E = CollAt (&L->JumpFrom, I);
|
CodeEntry* E = CollAt (&L->JumpFrom, I);
|
||||||
/* Remove the reference */
|
/* Remove the reference */
|
||||||
E->JumpTo = 0;
|
CE_ClearJumpTo (E);
|
||||||
}
|
}
|
||||||
CollDeleteAll (&L->JumpFrom);
|
CollDeleteAll (&L->JumpFrom);
|
||||||
|
|
||||||
@@ -875,7 +875,10 @@ void CS_MergeLabels (CodeSeg* S)
|
|||||||
for (J = 0; J < CL_GetRefCount (X); ++J) {
|
for (J = 0; J < CL_GetRefCount (X); ++J) {
|
||||||
/* Get the entry referencing this label */
|
/* Get the entry referencing this label */
|
||||||
CodeEntry* E = CL_GetRef (X, J);
|
CodeEntry* E = CL_GetRef (X, J);
|
||||||
/* And remove the reference */
|
/* And remove the reference. Do NOT call CE_ClearJumpTo
|
||||||
|
* here, because this will also clear the label name,
|
||||||
|
* which is not what we want.
|
||||||
|
*/
|
||||||
E->JumpTo = 0;
|
E->JumpTo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,7 +1002,7 @@ void CS_RemoveLabelRef (CodeSeg* S, struct CodeEntry* E)
|
|||||||
CollDeleteItem (&L->JumpFrom, E);
|
CollDeleteItem (&L->JumpFrom, E);
|
||||||
|
|
||||||
/* The entry jumps no longer to L */
|
/* The entry jumps no longer to L */
|
||||||
E->JumpTo = 0;
|
CE_ClearJumpTo (E);
|
||||||
|
|
||||||
/* If there are no more references, delete the label */
|
/* If there are no more references, delete the label */
|
||||||
if (CollCount (&L->JumpFrom) == 0) {
|
if (CollCount (&L->JumpFrom) == 0) {
|
||||||
|
|||||||
Reference in New Issue
Block a user