]> git.sur5r.net Git - cc65/blobdiff - src/cc65/symtab.c
Clean-up
[cc65] / src / cc65 / symtab.c
index 3275332c5490c68b89ab7a5c4b6e560716574144..f7fb07f61dae2e9f542fa4015c63c2dad915d80c 100644 (file)
@@ -57,6 +57,8 @@
 #include "symentry.h"
 #include "typecmp.h"
 #include "symtab.h"
+#include "function.h"
+#include "input.h"
 
 
 
@@ -658,10 +660,30 @@ SymEntry* AddConstSym (const char* Name, const Type* T, unsigned Flags, long Val
 }
 
 
+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) {
@@ -670,6 +692,47 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
             /* 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 {
@@ -678,16 +741,25 @@ SymEntry* AddLabelSym (const char* Name, unsigned Flags)
         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;
 }
@@ -717,12 +789,12 @@ SymEntry* AddLocalSym (const char* Name, const Type* T, unsigned Flags, int Offs
             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 {