]> git.sur5r.net Git - cc65/blobdiff - src/cc65/codeseg.c
Place all declarations that are local to a function into the local function
[cc65] / src / cc65 / codeseg.c
index bbc21337a4170e0328a1d9317c96e9db108ffb43..d52b36fcdba0d90f7190ff16d11dd8f88b594db1 100644 (file)
 
 
 
+static void CS_PrintFunctionHeader (const CodeSeg* S, FILE* F)
+/* Print a comment with the function signature to the given file */
+{
+    /* Get the associated function */
+    const SymEntry* Func = S->Func;
+
+    /* If this is a global code segment, do nothing */
+    if (Func) {
+        fprintf (F,
+                 "; ---------------------------------------------------------------\n"
+                 "; ");
+        PrintFuncSig (F, Func->Name, Func->Type);
+        fprintf (F,
+                 "\n"
+                 "; ---------------------------------------------------------------\n"
+                 "\n");
+    }
+}
+
+
+
 static void CS_MoveLabelsToEntry (CodeSeg* S, CodeEntry* E)
 /* Move all labels from the label pool to the given entry and remove them
  * from the pool.
@@ -161,7 +182,7 @@ static void CS_RemoveLabelFromHash (CodeSeg* S, CodeLabel* L)
 
 
 static CodeLabel* CS_AddLabelInternal (CodeSeg* S, const char* Name,
-                                      void (*ErrorFunc) (const char*, ...))
+                                      void (*ErrorFunc) (const char*, ...))
 /* Add a code label for the next instruction to follow */
 {
     /* Calculate the hash from the name */
@@ -725,6 +746,36 @@ unsigned CS_GetEntryIndex (CodeSeg* S, struct CodeEntry* E)
 
 
 
+int CS_RangeHasLabel (CodeSeg* S, unsigned Start, unsigned Count)
+/* Return true if any of the code entries in the given range has a label
+ * attached. If the code segment does not span the given range, check the
+ * possible span instead.
+ */
+{
+    unsigned EntryCount = CS_GetEntryCount(S);
+
+    /* Adjust count. We expect at least Start to be valid. */
+    CHECK (Start < EntryCount);
+    if (Start + Count > EntryCount) {
+       Count = EntryCount - Start;
+    }
+
+    /* Check each entry. Since we have validated the index above, we may
+     * use the unchecked access function in the loop which is faster.
+     */
+    while (Count--) {
+       const CodeEntry* E = CollAtUnchecked (&S->Entries, Start++);
+       if (CE_HasLabel (E)) {
+           return 1;
+       }
+    }
+
+    /* No label in the complete range */
+    return 0;
+}
+
+
+
 CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name)
 /* Add a code label for the next instruction to follow */
 {
@@ -806,6 +857,7 @@ void CS_MergeLabels (CodeSeg* S)
  */
 {
     unsigned I;
+    unsigned J;
 
     /* 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
@@ -817,12 +869,25 @@ void CS_MergeLabels (CodeSeg* S)
        CodeLabel** L = &S->LabelHash[I];
        while (*L) {
            if ((*L)->Owner == 0) {
-               /* The label does not have an owner, remove it from the chain */
+
+               /* The label does not have an owner, remove it from the chain */
                CodeLabel* X = *L;
                        *L = X->Next;
+
+               /* Cleanup any entries jumping to this label */
+               for (J = 0; J < CL_GetRefCount (X); ++J) {
+                   /* Get the entry referencing this label */
+                   CodeEntry* E = CL_GetRef (X, J);
+                   /* And remove the reference */
+                   E->JumpTo = 0;
+               }
+
+               /* Print some debugging output */
                if (Debug) {
                    printf ("Removing unused global label `%s'", X->Name);
                }
+
+               /* And free the label */
                FreeCodeLabel (X);
            } else {
                /* Label is owned, point to next code label pointer */
@@ -1028,6 +1093,41 @@ void CS_DelCodeAfter (CodeSeg* S, unsigned Last)
 
 
 
+void CS_OutputPrologue (const CodeSeg* S, FILE* F)
+/* If the given code segment is a code segment for a function, output the
+ * assembler prologue into the file. That is: Output a comment header, switch
+ * to the correct segment and enter the local function scope. If the code
+ * segment is global, do nothing.
+ */
+{
+    /* Get the function associated with the code segment */
+    SymEntry* Func = S->Func;
+
+    /* If the code segment is associated with a function, print a function
+     * header and enter a local scope. Be sure to switch to the correct
+     * segment before outputing the function label.
+     */
+    if (Func) {
+               CS_PrintFunctionHeader (S, F);
+        fprintf (F, ".segment\t\"%s\"\n\n.proc\t_%s\n\n", S->SegName, Func->Name);
+    }
+
+}
+
+
+
+void CS_OutputEpilogue (const CodeSeg* S, FILE* F)
+/* If the given code segment is a code segment for a function, output the
+ * assembler epilogue into the file. That is: Close the local function scope.
+ */
+{
+    if (S->Func) {
+       fprintf (F, "\n.endproc\n\n");
+    }
+}
+
+
+
 void CS_Output (const CodeSeg* S, FILE* F)
 /* Output the code segment data to a file */
 {
@@ -1045,11 +1145,6 @@ void CS_Output (const CodeSeg* S, FILE* F)
     /* Output the segment directive */
     fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
 
-    /* If this is a segment for a function, enter a function */
-    if (S->Func) {
-       fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
-    }
-
     /* Output all entries, prepended by the line information if it has changed */
     LI = 0;
     for (I = 0; I < Count; ++I) {
@@ -1082,11 +1177,6 @@ void CS_Output (const CodeSeg* S, FILE* F)
     if (DebugInfo) {
        fprintf (F, "\t.dbg\tline\n");
     }
-
-    /* If this is a segment for a function, leave the function */
-    if (S->Func) {
-       fprintf (F, "\n.endproc\n\n");
-    }
 }
 
 
@@ -1119,7 +1209,7 @@ void CS_GenRegInfo (CodeSeg* S)
 
        /* Assume we're done after this run */
        Done = 1;
-    
+
        /* On entry, the register contents are unknown */
        RC_Invalidate (&Regs);
        CurrentRegs = &Regs;
@@ -1194,33 +1284,33 @@ void CS_GenRegInfo (CodeSeg* S)
                    }
                    ++Entry;
                }
-    
+
                /* Use this register info */
                CurrentRegs = &Regs;
-    
+
            }
-    
+
            /* Generate register info for this instruction */
            CE_GenRegInfo (E, CurrentRegs);
-    
+
            /* Remember for the next insn if this insn was an uncondition branch */
            WasJump = (E->Info & OF_UBRA) != 0;
 
            /* Output registers for this insn are input for the next */
            CurrentRegs = &E->RI->Out;
-    
+
            /* If this insn is a branch on zero flag, we may have more info on
             * register contents for one of both flow directions, but only if
             * there is a previous instruction.
             */
            if ((E->Info & OF_ZBRA) != 0 && (P = CS_GetPrevEntry (S, I)) != 0) {
-    
+
                /* Get the branch condition */
                bc_t BC = GetBranchCond (E->OPC);
-    
+
                /* Check the previous instruction */
                switch (P->OPC) {
-    
+
                    case OP65_ADC:
                    case OP65_AND:
                    case OP65_DEA:
@@ -1237,7 +1327,7 @@ void CS_GenRegInfo (CodeSeg* S)
                            E->RI->Out.RegA = 0;
                        }
                        break;
-    
+
                    case OP65_CMP:
                        /* If this is an immidiate compare, the A register has
                         * the value of the compare later.
@@ -1250,7 +1340,7 @@ void CS_GenRegInfo (CodeSeg* S)
                            }
                        }
                        break;
-    
+
                    case OP65_CPX:
                        /* If this is an immidiate compare, the X register has
                         * the value of the compare later.
@@ -1263,7 +1353,7 @@ void CS_GenRegInfo (CodeSeg* S)
                            }
                        }
                        break;
-    
+
                    case OP65_CPY:
                        /* If this is an immidiate compare, the Y register has
                         * the value of the compare later.
@@ -1276,7 +1366,7 @@ void CS_GenRegInfo (CodeSeg* S)
                            }
                        }
                        break;
-    
+
                    case OP65_DEX:
                    case OP65_INX:
                    case OP65_LDX:
@@ -1288,7 +1378,7 @@ void CS_GenRegInfo (CodeSeg* S)
                            E->RI->Out.RegX = 0;
                        }
                        break;
-    
+
                    case OP65_DEY:
                    case OP65_INY:
                    case OP65_LDY:
@@ -1300,7 +1390,7 @@ void CS_GenRegInfo (CodeSeg* S)
                            E->RI->Out.RegY = 0;
                        }
                        break;
-    
+
                    case OP65_TAX:
                    case OP65_TXA:
                        /* If the branch is a beq, both A and X are zero at the
@@ -1313,7 +1403,7 @@ void CS_GenRegInfo (CodeSeg* S)
                            E->RI->Out.RegA = E->RI->Out.RegX = 0;
                        }
                        break;
-    
+
                    case OP65_TAY:
                    case OP65_TYA:
                        /* If the branch is a beq, both A and Y are zero at the
@@ -1326,10 +1416,10 @@ void CS_GenRegInfo (CodeSeg* S)
                            E->RI->Out.RegA = E->RI->Out.RegY = 0;
                        }
                        break;
-    
+
                    default:
                        break;
-    
+
                }
            }
        }