1
0
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:
laubzega 2018-09-25 00:56:08 -07:00 committed by Oliver Schmidt
parent a48bbc4be0
commit 2ac2ffcd43
4 changed files with 62 additions and 4 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
} }