mirror of
https://github.com/cc65/cc65.git
synced 2024-06-26 05:29:30 +00:00
Adjust SP on gotos between blocks with local variables.
This commit is contained in:
parent
a48bbc4be0
commit
2ac2ffcd43
|
@ -2425,6 +2425,19 @@ void g_falsejump (unsigned flags attribute ((unused)), unsigned label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void g_lateadjustSP (unsigned label)
|
||||||
|
{
|
||||||
|
/* Adjust stack based on non-immediate data */
|
||||||
|
AddCodeLine ("pha");
|
||||||
|
AddCodeLine ("lda %s", LocalLabelName (label));
|
||||||
|
AddCodeLine ("clc");
|
||||||
|
AddCodeLine ("adc sp");
|
||||||
|
AddCodeLine ("sta sp");
|
||||||
|
AddCodeLine ("lda %s+1", LocalLabelName (label));
|
||||||
|
AddCodeLine ("adc sp+1");
|
||||||
|
AddCodeLine ("sta sp+1");
|
||||||
|
AddCodeLine ("pla");
|
||||||
|
}
|
||||||
|
|
||||||
void g_drop (unsigned Space)
|
void g_drop (unsigned Space)
|
||||||
/* Drop space allocated on the stack */
|
/* Drop space allocated on the stack */
|
||||||
|
|
|
@ -406,6 +406,9 @@ void g_truejump (unsigned flags, unsigned label);
|
||||||
void g_falsejump (unsigned flags, unsigned label);
|
void g_falsejump (unsigned flags, unsigned label);
|
||||||
/* Jump to label if zero flag set */
|
/* Jump to label if zero flag set */
|
||||||
|
|
||||||
|
void g_lateadjustSP (unsigned label);
|
||||||
|
/* Adjust stack based on non-immediate data */
|
||||||
|
|
||||||
void g_drop (unsigned Space);
|
void g_drop (unsigned Space);
|
||||||
/* Drop space allocated on the stack */
|
/* Drop space allocated on the stack */
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,9 @@ struct DefOrRef {
|
||||||
unsigned Line;
|
unsigned Line;
|
||||||
long LocalsBlockNum;
|
long LocalsBlockNum;
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
|
int StackPtr;
|
||||||
|
unsigned Depth;
|
||||||
|
unsigned LateSP_Label;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Symbol table entry */
|
/* Symbol table entry */
|
||||||
|
|
|
@ -670,6 +670,9 @@ DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
|
||||||
DOR->Line = GetCurrentLine ();
|
DOR->Line = GetCurrentLine ();
|
||||||
DOR->LocalsBlockNum = (long)CollLast (&CurrentFunc->LocalsBlockStack);
|
DOR->LocalsBlockNum = (long)CollLast (&CurrentFunc->LocalsBlockStack);
|
||||||
DOR->Flags = Flags;
|
DOR->Flags = Flags;
|
||||||
|
DOR->StackPtr = StackPtr;
|
||||||
|
DOR->Depth = CollCount(&CurrentFunc->LocalsBlockStack);
|
||||||
|
DOR->LateSP_Label = GetLocalLabel();
|
||||||
|
|
||||||
return DOR;
|
return DOR;
|
||||||
}
|
}
|
||||||
|
@ -679,7 +682,8 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
||||||
/* Add a goto label to the label table */
|
/* Add a goto label to the label table */
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
DefOrRef *DOR;
|
DefOrRef *DOR, *NewDOR;
|
||||||
|
|
||||||
/* Do we have an entry with this name already? */
|
/* Do we have an entry with this name already? */
|
||||||
SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
|
SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
|
||||||
if (Entry) {
|
if (Entry) {
|
||||||
|
@ -689,6 +693,8 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
||||||
Error ("Label `%s' is defined more than once", Name);
|
Error ("Label `%s' is defined more than once", Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NewDOR = AddDefOrRef (Entry, Flags);
|
||||||
|
|
||||||
/* Walk through all occurrences of the label so far and check
|
/* Walk through all occurrences of the label so far and check
|
||||||
if any of them is in a region that would be risky to jump from/to
|
if any of them is in a region that would be risky to jump from/to
|
||||||
from the place where we are right now. */
|
from the place where we are right now. */
|
||||||
|
@ -698,13 +704,41 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
||||||
the one currently being added, i.e. if we are processing the
|
the one currently being added, i.e. if we are processing the
|
||||||
definition, we will only check the gotos; if we are processing
|
definition, we will only check the gotos; if we are processing
|
||||||
a goto statement, we will only look for the label definition. */
|
a goto statement, we will only look for the label definition. */
|
||||||
|
/*
|
||||||
if (((DOR->Flags & SC_DEF) != (Flags & SC_DEF)) &&
|
if (((DOR->Flags & SC_DEF) != (Flags & SC_DEF)) &&
|
||||||
|
(CollCount(&CurrentFunc->LocalsBlockStack) == DOR->Depth) &&
|
||||||
(DOR->LocalsBlockNum != (long)CollLast (&CurrentFunc->LocalsBlockStack)))
|
(DOR->LocalsBlockNum != (long)CollLast (&CurrentFunc->LocalsBlockStack)))
|
||||||
Error ("Goto from line %d to label \'%s\' can result in a "
|
Error ("Goto from line %d to label \'%s\' can result in a "
|
||||||
"trashed stack", Flags & SC_DEF ? DOR->Line : GetCurrentLine (), Name);
|
"trashed stack", Flags & SC_DEF ? DOR->Line : GetCurrentLine (), Name);
|
||||||
}
|
*/
|
||||||
|
if((DOR->Flags & SC_DEF) && (Flags & SC_REF)) {
|
||||||
|
/* We're processing a goto and here is its destination label.
|
||||||
|
This means the difference between SP values is also known, so
|
||||||
|
we simply emit SP adjustment code. */
|
||||||
|
if(StackPtr != DOR->StackPtr)
|
||||||
|
g_space(StackPtr - DOR->StackPtr);
|
||||||
|
|
||||||
AddDefOrRef (Entry, Flags);
|
if (CollCount(&CurrentFunc->LocalsBlockStack) <= DOR->Depth &&
|
||||||
|
DOR->LocalsBlockNum != (long)CollLast (&CurrentFunc->LocalsBlockStack)) {
|
||||||
|
Warning ("Goto from line %d to label \'%s\' can result in a "
|
||||||
|
"trashed stack", DOR->Line, Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((DOR->Flags & SC_REF) && (Flags & SC_DEF)) {
|
||||||
|
/* We're processing a label, let's update all gotos encountered
|
||||||
|
so far */
|
||||||
|
g_defdatalabel(DOR->LateSP_Label);
|
||||||
|
g_defdata(CF_CONST | CF_INT, StackPtr - DOR->StackPtr, 0);
|
||||||
|
|
||||||
|
if (CollCount(&CurrentFunc->LocalsBlockStack) >= DOR->Depth &&
|
||||||
|
DOR->LocalsBlockNum != (long)CollLast (&CurrentFunc->LocalsBlockStack)) {
|
||||||
|
Warning ("Goto from line %d to label \'%s\' can result in a "
|
||||||
|
"trashed stack", DOR->Line, Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Entry->Flags |= Flags;
|
Entry->Flags |= Flags;
|
||||||
|
|
||||||
|
@ -718,7 +752,7 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
||||||
|
|
||||||
/* Create Collection for label definition and references */
|
/* Create Collection for label definition and references */
|
||||||
Entry->V.L.DefsOrRefs = NewCollection ();
|
Entry->V.L.DefsOrRefs = NewCollection ();
|
||||||
AddDefOrRef (Entry, Flags);
|
NewDOR = AddDefOrRef (Entry, Flags);
|
||||||
|
|
||||||
/* Generate the assembler name of the label */
|
/* Generate the assembler name of the label */
|
||||||
Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
|
Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
|
||||||
|
@ -728,6 +762,11 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We are processing a goto, but the label has not yet been defined */
|
||||||
|
if (!SymIsDef (Entry) && (Flags & SC_REF)) {
|
||||||
|
g_lateadjustSP(NewDOR->LateSP_Label);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the entry */
|
/* Return the entry */
|
||||||
return Entry;
|
return Entry;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user