]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codeseg.c
Fixed two compiler warnings.
[cc65] / src / cc65 / codeseg.c
index b8466a492447e52a19fbac247507c5d6afd1e55d..fff502d3ea6009f44a73b287499511641da8a9a5 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2001-2009, Ullrich von Bassewitz                                      */
+/* (C) 2001-2011, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -41,7 +41,7 @@
 #include "check.h"
 #include "debugflag.h"
 #include "global.h"
-#include "hashstr.h"
+#include "hashfunc.h"
 #include "strbuf.h"
 #include "strutil.h"
 #include "xmalloc.h"
@@ -337,13 +337,13 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
                if (*L == ',') {
                    L = SkipSpace (L+1);
                    if (toupper (*L) != 'Y') {
-                       Error ("ASM code error: `Y' expected");
+                       Error ("ASM code error: `Y' expected");
                        return 0;
                    }
                    L = SkipSpace (L+1);
                    if (*L != '\0') {
-                       Error ("ASM code error: syntax error");
-                       return 0;
+                       Error ("ASM code error: syntax error");
+                       return 0;
                    }
                    AM = AM65_ZP_INDY;
                } else if (*L == '\0') {
@@ -375,6 +375,12 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
                } else if (GetZPInfo(Arg) != 0) {
                    AM = AM65_ZP;
                } else {
+                    /* Check for subroutine call to local label */
+                    if ((OPC->Info & OF_CALL) && IsLocalLabelName (Arg)) {
+                        Error ("ASM code error: "
+                               "Cannot use local label `%s' in subroutine call",
+                               Arg);
+                    }
                    AM = AM65_ABS;
                }
            } else if (*L == ',') {
@@ -387,20 +393,20 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
                    Reg = toupper (*L);
                    L = SkipSpace (L+1);
                    if (Reg == 'X') {
-                       if (GetZPInfo(Arg) != 0) {
-                           AM = AM65_ZPX;
-                       } else {
-                           AM = AM65_ABSX;
-                       }
+                       if (GetZPInfo(Arg) != 0) {
+                           AM = AM65_ZPX;
+                       } else {
+                           AM = AM65_ABSX;
+                       }
                    } else if (Reg == 'Y') {
-                       AM = AM65_ABSY;
+                       AM = AM65_ABSY;
                    } else {
-                       Error ("ASM code error: syntax error");
-                       return 0;
+                       Error ("ASM code error: syntax error");
+                       return 0;
                    }
                    if (*L != '\0') {
-                       Error ("ASM code error: syntax error");
-                       return 0;
+                       Error ("ASM code error: syntax error");
+                       return 0;
                    }
                }
            }
@@ -649,6 +655,11 @@ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos
  * current code end)
  */
 {
+    /* Transparently handle an empty range */
+    if (Count == 0) {
+        return;
+    }
+
     /* If NewPos is at the end of the code segment, move any labels from the
      * label pool to the first instruction of the moved range.
      */
@@ -1044,6 +1055,86 @@ void CS_MoveLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L)
 
 
 
+void CS_DelCodeRange (CodeSeg* S, unsigned First, unsigned Last)
+/* Delete all entries between first and last, both inclusive. The function
+ * can only handle basic blocks (First is the only entry, Last the only exit)
+ * and no open labels. It will call FAIL if any of these preconditions are
+ * violated.
+ */
+{
+    unsigned   I;
+    CodeEntry* FirstEntry;
+
+    /* Do some sanity checks */
+    CHECK (First <= Last && Last < CS_GetEntryCount (S));
+
+    /* If Last is actually the last insn, call CS_DelCodeAfter instead, which
+     * is more flexible in this case.
+     */
+    if (Last == CS_GetEntryCount (S) - 1) {
+        CS_DelCodeAfter (S, First);
+        return;
+    }
+
+    /* Get the first entry and check if it has any labels. If it has, move
+     * them to the insn following Last. If Last is the last insn of the code
+     * segment, make them ownerless and move them to the label pool.
+     */
+    FirstEntry = CS_GetEntry (S, First);
+    if (CE_HasLabel (FirstEntry)) {
+        /* Get the entry following last */
+        CodeEntry* FollowingEntry = CS_GetNextEntry (S, Last);
+        if (FollowingEntry) {
+            /* There is an entry after Last - move the labels */
+            CS_MoveLabels (S, FirstEntry, FollowingEntry);
+        } else {
+           /* Move the labels to the pool and clear the owner pointer */
+           CS_MoveLabelsToPool (S, FirstEntry);
+        }
+    }
+
+    /* First pass: Delete all references to labels. If the reference count
+     * for a label drops to zero, delete it.
+     */
+    for (I = Last; I >= First; --I) {
+
+               /* Get the next entry */
+               CodeEntry* E = CS_GetEntry (S, I);
+
+               /* Check if this entry has a label reference */
+               if (E->JumpTo) {
+
+                   /* If the label is a label in the label pool, this is an error */
+                   CodeLabel* L = E->JumpTo;
+                   CHECK (CollIndex (&S->Labels, L) < 0);
+
+           /* Remove the reference to the label */
+           CS_RemoveLabelRef (S, E);
+       }
+    }
+
+    /* Second pass: Delete the instructions. If a label attached to an
+     * instruction still has references, it must be references from outside
+     * the deleted area, which is an error.
+     */
+    for (I = Last; I >= First; --I) {
+
+       /* Get the next entry */
+       CodeEntry* E = CS_GetEntry (S, I);
+
+               /* Check if this entry has a label attached */
+       CHECK (!CE_HasLabel (E));
+
+       /* Delete the pointer to the entry */
+       CollDelete (&S->Entries, I);
+
+       /* Delete the entry itself */
+       FreeCodeEntry (E);
+    }
+}
+
+
+
 void CS_DelCodeAfter (CodeSeg* S, unsigned Last)
 /* Delete all entries including the given one */
 {
@@ -1309,7 +1400,7 @@ void CS_Output (CodeSeg* S)
                     const char* N = strchr (L, '\n');
                     if (N) {
                         /* We have a newline, just write the first part */
-                        WriteOutput ("%.*s\n; ", N - L, L);
+                        WriteOutput ("%.*s\n; ", (int) (N - L), L);
                         L = N+1;
                     } else {
                         /* No Newline, write as is */