#include "symentry.h"
#include "typecmp.h"
#include "symtab.h"
+#include "function.h"
+#include "input.h"
}
+DefOrRef* AddDefOrRef(SymEntry* E, unsigned Flags)
+/* Add definition or reference to the SymEntry and preserve its attributes */
+{
+ DefOrRef *DOR;
+
+ DOR = xmalloc (sizeof (DefOrRef));
+ CollAppend (E->V.L.DefsOrRefs, DOR);
+ DOR->Line = GetCurrentLine ();
+ DOR->LocalsBlockNum = (long)CollLast (&CurrentFunc->LocalsBlockStack);
+ DOR->Flags = Flags;
+ DOR->StackPtr = StackPtr;
+ DOR->Depth = CollCount (&CurrentFunc->LocalsBlockStack);
+ DOR->LateSP_Label = GetLocalLabel ();
+
+ return DOR;
+}
+
SymEntry* AddLabelSym (const char* Name, unsigned Flags)
/* Add a goto label to the label table */
{
+ unsigned i;
+ DefOrRef *DOR, *NewDOR;
+
/* Do we have an entry with this name already? */
SymEntry* Entry = FindSymInTable (LabelTab, Name, HashStr (Name));
if (Entry) {
/* Trying to define the label more than once */
Error ("Label `%s' is defined more than once", Name);
}
+
+ NewDOR = AddDefOrRef (Entry, Flags);
+
+ /* Walk through all occurrences of the label so far and evaluate
+ their relationship with the one passed to the function. */
+ for (i = 0; i < CollCount (Entry->V.L.DefsOrRefs); i++) {
+ DOR = CollAt (Entry->V.L.DefsOrRefs, i);
+
+ 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 already known,
+ so we simply emit the SP adjustment code. */
+ if(StackPtr != DOR->StackPtr)
+ g_space (StackPtr - DOR->StackPtr);
+
+ /* Are we jumping into same or deeper nesting region? That's risky,
+ so let's emit a warning. */
+ 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);
+
+ /* Are we jumping into same or deeper nesting region? That's risky,
+ so let's emit a warning. */
+ 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;
} else {
Entry = NewSymEntry (Name, SC_LABEL | Flags);
/* Set a new label number */
- Entry->V.Label = GetLocalLabel ();
+ Entry->V.L.Label = GetLocalLabel ();
+
+ /* Create Collection for label definition and references */
+ Entry->V.L.DefsOrRefs = NewCollection ();
+ NewDOR = AddDefOrRef (Entry, Flags);
/* Generate the assembler name of the label */
- Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
+ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
/* Add the entry to the label table */
AddSymEntry (LabelTab, Entry);
}
+ /* 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 Entry;
}
Entry->V.R.RegOffs = Offs;
Entry->V.R.SaveOffs = StackPtr;
} else if ((Flags & SC_EXTERN) == SC_EXTERN) {
- Entry->V.Label = Offs;
+ Entry->V.L.Label = Offs;
SymSetAsmName (Entry);
} else if ((Flags & SC_STATIC) == SC_STATIC) {
/* Generate the assembler name from the label number */
- Entry->V.Label = Offs;
- Entry->AsmName = xstrdup (LocalLabelName (Entry->V.Label));
+ Entry->V.L.Label = Offs;
+ Entry->AsmName = xstrdup (LocalLabelName (Entry->V.L.Label));
} else if ((Flags & SC_STRUCTFIELD) == SC_STRUCTFIELD) {
Entry->V.Offs = Offs;
} else {