]> git.sur5r.net Git - cc65/commitdiff
More work to make user asm labels work
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 12 Oct 2001 07:58:11 +0000 (07:58 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Fri, 12 Oct 2001 07:58:11 +0000 (07:58 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@1043 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/codelab.c
src/cc65/codeseg.c
src/cc65/coptcmp.c

index db4341d8737fc49c54851a856b21e24766d19873..f4c14ea752ed038bbfaab45b67f6ab8f91803ae6 100644 (file)
@@ -123,8 +123,12 @@ void CL_Output (const CodeLabel* L, FILE* F)
 /* Output the code label to a file */
 {
     fprintf (F, "%s:", L->Name);
+    if (strlen (L->Name) > 6) {
+       /* Label is too long, add a linefeed */
+       fputc ('\n', F);
+    }
 }
 
 
 
-                       
+
index 6fee2f809ddfc07990a81bfcbefb79aee29b7457..a846296a5b401e7c651a72fe1dfe623ce3e99baa 100644 (file)
@@ -174,9 +174,9 @@ static CodeLabel* CS_AddLabelInternal (CodeSeg* S, const char* Name, int UserCod
        /* We found it - be sure it does not already have an owner */
        if (L->Owner) {
            if (UserCode) {
-               Error ("ASM label `%s' is already defined", Name);
+               Error ("ASM label `%s' is already defined", Name);
            } else {
-               Internal ("CS_AddLabelInternal: Label `%s' already defined", Name);
+               Internal ("CS_AddLabelInternal: Label `%s' already defined", Name);
            }
        }
     } else {
@@ -220,7 +220,7 @@ static const char* SkipSpace (const char* S)
 
 
 static const char* ReadToken (const char* L, const char* Term,
-                             char* Buf, unsigned BufSize)
+                             char* Buf, unsigned BufSize)
 /* Read the next token into Buf, return the updated line pointer. The
  * token is terminated by one of the characters given in term.
  */
@@ -230,8 +230,14 @@ static const char* ReadToken (const char* L, const char* Term,
     unsigned ParenCount = 0;
     while (*L && (ParenCount > 0 || strchr (Term, *L) == 0)) {
        if (I < BufSize-1) {
-           Buf[I++] = *L;
+           Buf[I] = *L;
+       } else if (I == BufSize-1) {
+           /* Cannot store this character, this is an input error (maybe
+            * identifier too long or similar).
+            */
+           Error ("ASM code error: syntax error");
        }
+       ++I;
        if (*L == ')') {
            --ParenCount;
        } else if (*L == '(') {
@@ -257,11 +263,11 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
  * white space, for example.
  */
 {
-    char                       Mnemo[16];
+    char                       Mnemo[64];
     const OPCDesc*     OPC;
     am_t               AM = 0;         /* Initialize to keep gcc silent */
     char               Arg[64];
-    char               Reg;
+    char               Reg;
     CodeEntry*         E;
     CodeLabel*         Label;
 
@@ -347,7 +353,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
                    L = SkipSpace (L+1);
                    if (toupper (*L) != 'Y') {
                        Error ("ASM code error: `Y' expected");
-                       return 0;
+                       return 0;
                    }
                    L = SkipSpace (L+1);
                    if (*L != '\0') {
@@ -418,10 +424,12 @@ static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
     }
 
     /* If the instruction is a branch, check for the label and generate it
-     * if it does not exist. Ignore anything but local labels here.
+     * if it does not exist. This may lead to unused labels (if the label
+     * is actually an external one) which are removed by the CS_MergeLabels
+     * function later.
      */
     Label = 0;
-    if (AM == AM65_BRA && Arg[0] == 'L') {
+    if (AM == AM65_BRA) {
 
        /* Generate the hash over the label, then search for the label */
        unsigned Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE;
@@ -806,45 +814,69 @@ void CS_MergeLabels (CodeSeg* S)
 {
     unsigned I;
 
+    /* First, remove all labels from the label symbol table that don't have an
+     * owner (this means that they are actually external labels but we didn't
+     * know that previously since they may have also been forward references).
+     */
+    for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) {
+
+       /* Get the first label in this hash chain */
+       CodeLabel** L = &S->LabelHash[I];
+       while (*L) {
+           if ((*L)->Owner == 0) {
+               /* The label does not have an owner, remove it from the chain */
+               CodeLabel* X = *L;
+                       *L = X->Next;
+               if (Debug) {
+                   printf ("Removing unused global label `%s'", X->Name);
+               }
+               FreeCodeLabel (X);
+           } else {
+               /* Label is owned, point to next code label pointer */
+               L = &((*L)->Next);
+           }
+       }
+    }
+
     /* Walk over all code entries */
     for (I = 0; I < CS_GetEntryCount (S); ++I) {
 
                CodeLabel* RefLab;
                unsigned   J;
 
-       /* Get a pointer to the next entry */
-       CodeEntry* E = CS_GetEntry (S, I);
+       /* Get a pointer to the next entry */
+       CodeEntry* E = CS_GetEntry (S, I);
 
        /* If this entry has zero labels, continue with the next one */
-       unsigned LabelCount = CE_GetLabelCount (E);
-       if (LabelCount == 0) {
-           continue;
-       }
-
-       /* We have at least one label. Use the first one as reference label. */
-       RefLab = CE_GetLabel (E, 0);
-
-       /* Walk through the remaining labels and change references to these
-        * labels to a reference to the one and only label. Delete the labels
-        * that are no longer used. To increase performance, walk backwards
-        * through the list.
-        */
+       unsigned LabelCount = CE_GetLabelCount (E);
+       if (LabelCount == 0) {
+           continue;
+       }
+
+       /* We have at least one label. Use the first one as reference label. */
+       RefLab = CE_GetLabel (E, 0);
+
+       /* Walk through the remaining labels and change references to these
+        * labels to a reference to the one and only label. Delete the labels
+        * that are no longer used. To increase performance, walk backwards
+        * through the list.
+        */
        for (J = LabelCount-1; J >= 1; --J) {
 
-           /* Get the next label */
-           CodeLabel* L = CE_GetLabel (E, J);
+           /* Get the next label */
+           CodeLabel* L = CE_GetLabel (E, J);
 
-           /* Move all references from this label to the reference label */
+           /* Move all references from this label to the reference label */
            CL_MoveRefs (L, RefLab);
 
                    /* Remove the label completely. */
                    CS_DelLabel (S, L);
        }
 
-       /* The reference label is the only remaining label. Check if there
-        * are any references to this label, and delete it if this is not
-        * the case.
-        */
+       /* The reference label is the only remaining label. Check if there
+        * are any references to this label, and delete it if this is not
+        * the case.
+        */
                if (CollCount (&RefLab->JumpFrom) == 0) {
            /* Delete the label */
                    CS_DelLabel (S, RefLab);
index 38078477fee3c4fbf8358f9844f7a9e4e298edc6..b259d321eac6f09d2c0e99cc17c65a595c2489f2 100644 (file)
@@ -867,7 +867,8 @@ unsigned OptCmp7 (CodeSeg* S)
                    CS_DelEntry (S, I+1);
                } else {
                    CodeLabel* L = N->JumpTo;
-                   CodeEntry* X = NewCodeEntry (OP65_JMP, AM65_BRA, L->Name, L, N->LI);
+                   const char* LabelName = L? L->Name : N->Arg;
+                   CodeEntry* X = NewCodeEntry (OP65_JMP, AM65_BRA, LabelName, L, N->LI);
                    CS_InsertEntry (S, X, I+2);
                    CS_DelEntry (S, I+1);
                }