]> git.sur5r.net Git - cc65/blobdiff - src/cc65/function.c
Merge remote-tracking branch 'upstream/master' into a5200
[cc65] / src / cc65 / function.c
index b31bfd79696f5bdfba11f7271953bb4906681549..97c421951f57183b7ff684bc7530dcf72af16802 100644 (file)
@@ -1,12 +1,12 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                               function.c                                 */
+/*                                function.c                                 */
 /*                                                                           */
-/*                     Parse function entry/body/exit                       */
+/*                      Parse function entry/body/exit                       */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2000-2011, Ullrich von Bassewitz                                      */
+/* (C) 2000-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
@@ -56,7 +56,7 @@
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                   Data                                    */
 /*****************************************************************************/
 
 
@@ -71,14 +71,14 @@ typedef enum {
 
 /* Structure that holds all data needed for function activation */
 struct Function {
-    struct SymEntry*           FuncEntry;      /* Symbol table entry */
-    Type*              ReturnType;     /* Function return type */
-    FuncDesc*                  Desc;           /* Function descriptor */
-    int                        Reserved;       /* Reserved local space */
-    unsigned           RetLab;         /* Return code label */
-    int                        TopLevelSP;     /* SP at function top level */
+    struct SymEntry*    FuncEntry;      /* Symbol table entry */
+    Type*               ReturnType;     /* Function return type */
+    FuncDesc*           Desc;           /* Function descriptor */
+    int                 Reserved;       /* Reserved local space */
+    unsigned            RetLab;         /* Return code label */
+    int                 TopLevelSP;     /* SP at function top level */
     unsigned            RegOffs;        /* Register variable space offset */
-    funcflags_t                Flags;          /* Function flags */
+    funcflags_t         Flags;          /* Function flags */
 };
 
 /* Pointer to current function */
@@ -87,7 +87,7 @@ Function* CurrentFunc = 0;
 
 
 /*****************************************************************************/
-/*                        Subroutines working with struct Function                  */
+/*                 Subroutines working with struct Function                  */
 /*****************************************************************************/
 
 
@@ -101,12 +101,12 @@ static Function* NewFunction (struct SymEntry* Sym)
     /* Initialize the fields */
     F->FuncEntry  = Sym;
     F->ReturnType = GetFuncReturn (Sym->Type);
-    F->Desc      = GetFuncDesc (Sym->Type);
-    F->Reserved          = 0;
-    F->RetLab    = GetLocalLabel ();
+    F->Desc       = GetFuncDesc (Sym->Type);
+    F->Reserved   = 0;
+    F->RetLab     = GetLocalLabel ();
     F->TopLevelSP = 0;
     F->RegOffs    = RegisterSpace;
-    F->Flags     = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE;
+    F->Flags      = IsTypeVoid (F->ReturnType) ? FF_VOID_RETURN : FF_NONE;
 
     /* Return the new structure */
     return F;
@@ -237,6 +237,16 @@ int F_ReserveLocalSpace (Function* F, unsigned Size)
 
 
 
+int F_GetStackPtr (const Function* F)
+/* Return the current stack pointer including reserved (but not allocated)
+ * space on the stack.
+ */
+{
+    return StackPtr - F->Reserved;
+}
+
+
+
 void F_AllocLocalSpace (Function* F)
 /* Allocate any local space previously reserved. The function will do
  * nothing if there is no reserved local space.
@@ -244,14 +254,14 @@ void F_AllocLocalSpace (Function* F)
 {
     if (F->Reserved > 0) {
 
-               /* Create space on the stack */
-               g_space (F->Reserved);
+        /* Create space on the stack */
+        g_space (F->Reserved);
 
-               /* Correct the stack pointer */
-               StackPtr -= F->Reserved;
+        /* Correct the stack pointer */
+        StackPtr -= F->Reserved;
 
-               /* Nothing more reserved */
-               F->Reserved = 0;
+        /* Nothing more reserved */
+        F->Reserved = 0;
     }
 }
 
@@ -266,18 +276,18 @@ int F_AllocRegVar (Function* F, const Type* Type)
     /* Allow register variables only on top level and if enabled */
     if (IS_Get (&EnableRegVars) && GetLexicalLevel () == LEX_LEVEL_FUNCTION) {
 
-       /* Get the size of the variable */
-       unsigned Size = CheckedSizeOf (Type);
-
-       /* Do we have space left? */
-       if (F->RegOffs >= Size) {
-           /* Space left. We allocate the variables from high to low addresses,
-            * so the adressing is compatible with the saved values on stack.
-            * This allows shorter code when saving/restoring the variables.
-            */
-           F->RegOffs -= Size;
-           return F->RegOffs;
-       }
+        /* Get the size of the variable */
+        unsigned Size = CheckedSizeOf (Type);
+
+        /* Do we have space left? */
+        if (F->RegOffs >= Size) {
+            /* Space left. We allocate the variables from high to low addresses,
+             * so the adressing is compatible with the saved values on stack.
+             * This allows shorter code when saving/restoring the variables.
+             */
+            F->RegOffs -= Size;
+            return F->RegOffs;
+        }
     }
 
     /* No space left or no allocation */
@@ -293,12 +303,12 @@ static void F_RestoreRegVars (Function* F)
 
     /* If we don't have register variables in this function, bail out early */
     if (F->RegOffs == RegisterSpace) {
-               return;
+        return;
     }
 
     /* Save the accumulator if needed */
     if (!F_HasVoidReturn (F)) {
-               g_save (CF_CHAR | CF_FORCECHAR);
+        g_save (CF_CHAR | CF_FORCECHAR);
     }
 
     /* Get the first symbol from the function symbol table */
@@ -353,52 +363,31 @@ static void F_RestoreRegVars (Function* F)
 
     /* Restore the accumulator if needed */
     if (!F_HasVoidReturn (F)) {
-       g_restore (CF_CHAR | CF_FORCECHAR);
+        g_restore (CF_CHAR | CF_FORCECHAR);
     }
 }
 
 
 
-static void EmitDebugInfo (void)
+static void F_EmitDebugInfo (void)
 /* Emit debug infos for the current function */
 {
-    /* Fetch stuff for the current fuction */
-    const SymEntry* Sym = CurrentFunc->FuncEntry;
-    const FuncDesc* Desc = CurrentFunc->Desc;
-    const SymTable* Tab = Desc->SymTab;
-
-    /* Output info for the function itself */
-    AddTextLine ("\t.dbg\tfunc, \"%s\", %s, \"%s\"", 
-                 Sym->Name,
-                 (Sym->Flags & SC_EXTERN)? "extern" : "static",
-                 Sym->AsmName);
-
-    /* Output info for locals */
-    Sym = Tab->SymHead;
-    while (Sym) {
-        if ((Sym->Flags & (SC_CONST|SC_TYPE)) == 0) {
-            if (Sym->Flags & SC_AUTO) {
-                AddTextLine ("\t.dbg\tsym, \"%s\", auto, %d",
-                             Sym->Name, Sym->V.Offs);
-            } else if (Sym->Flags & SC_REGISTER) {
-                AddTextLine ("\t.dbg\tsym, \"%s\", register, %d",
-                             Sym->Name, Sym->V.R.RegOffs);
-
-            } else {
-                AddTextLine ("\t.dbg\tsym, \"%s\", %s, \"%s\"",
-                             Sym->Name,
-                             (Sym->Flags & SC_EXTERN)? "extern" : "static",
-                             Sym->AsmName);
-            }
-        }
-        Sym = Sym->NextSym;
+    if (DebugInfo) {
+        /* Get the current function */
+        const SymEntry* Sym = CurrentFunc->FuncEntry;
+
+        /* Output info for the function itself */
+        AddTextLine ("\t.dbg\tfunc, \"%s\", \"00\", %s, \"%s\"",
+                     Sym->Name,
+                     (Sym->Flags & SC_EXTERN)? "extern" : "static",
+                     Sym->AsmName);
     }
 }
 
 
 
 /*****************************************************************************/
-/*                                          code                                    */
+/*                                   code                                    */
 /*****************************************************************************/
 
 
@@ -431,12 +420,12 @@ void NewFunc (SymEntry* Func)
      */
     AddConstSym ("__fixargs__", type_uint, SC_DEF | SC_CONST, D->ParamSize);
     if (D->Flags & FD_VARIADIC) {
-       /* Variadic function. The variable must be const. */
-       static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) };
-       AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0);
+        /* Variadic function. The variable must be const. */
+        static const Type T[] = { TYPE(T_UCHAR | T_QUAL_CONST), TYPE(T_END) };
+        AddLocalSym ("__argsize__", T, SC_DEF | SC_REF | SC_AUTO, 0);
     } else {
-       /* Non variadic */
-               AddConstSym ("__argsize__", type_uchar, SC_DEF | SC_CONST, D->ParamSize);
+        /* Non variadic */
+        AddConstSym ("__argsize__", type_uchar, SC_DEF | SC_CONST, D->ParamSize);
     }
 
     /* Function body now defined */
@@ -491,19 +480,19 @@ void NewFunc (SymEntry* Func)
     /* If this is a fastcall function, push the last parameter onto the stack */
     if (IsQualFastcall (Func->Type) && D->ParamCount > 0) {
 
-       unsigned Flags;
+        unsigned Flags;
 
-       /* Fastcall functions may never have an ellipsis or the compiler is buggy */
-       CHECK ((D->Flags & FD_VARIADIC) == 0);
+        /* Fastcall functions may never have an ellipsis or the compiler is buggy */
+        CHECK ((D->Flags & FD_VARIADIC) == 0);
 
-       /* Generate the push */
-       if (IsTypeFunc (D->LastParam->Type)) {
-           /* Pointer to function */
-           Flags = CF_PTR;
-       } else {
-           Flags = TypeOf (D->LastParam->Type) | CF_FORCECHAR;
-       }
-       g_push (Flags, 0);
+        /* Generate the push */
+        if (IsTypeFunc (D->LastParam->Type)) {
+            /* Pointer to function */
+            Flags = CF_PTR;
+        } else {
+            Flags = TypeOf (D->LastParam->Type) | CF_FORCECHAR;
+        }
+        g_push (Flags, 0);
     }
 
     /* Generate function entry code if needed */
@@ -511,7 +500,7 @@ void NewFunc (SymEntry* Func)
 
     /* If stack checking code is requested, emit a call to the helper routine */
     if (IS_Get (&CheckStack)) {
-       g_stackcheck ();
+        g_stackcheck ();
     }
 
     /* Setup the stack */
@@ -593,6 +582,7 @@ void NewFunc (SymEntry* Func)
     EmitExternals ();
 
     /* Emit function debug info */
+    F_EmitDebugInfo ();
     EmitDebugInfo ();
 
     /* Leave the lexical level */
@@ -611,6 +601,3 @@ void NewFunc (SymEntry* Func)
     FreeFunction (CurrentFunc);
     CurrentFunc = 0;
 }
-
-
-