]> git.sur5r.net Git - cc65/commitdiff
Use one function exit point
authorcuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 26 Mar 2001 20:07:05 +0000 (20:07 +0000)
committercuz <cuz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Mon, 26 Mar 2001 20:07:05 +0000 (20:07 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@674 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/function.c
src/cc65/function.h
src/cc65/stmt.c
src/cc65/stmt.h

index d9efc9a7700ab3dbd932d3ac53c0eddb7e40c48b..b4340b85e814e3207f6dea88c4383cd5c6809b5e 100644 (file)
@@ -64,9 +64,9 @@ struct Function {
     struct SymEntry*           FuncEntry;      /* Symbol table entry */
     type*              ReturnType;     /* Function return type */
     struct FuncDesc*   Desc;           /* Function descriptor */
-    CodeMark           EntryCode;      /* Backpatch addr for entry code */
     int                        Reserved;       /* Reserved local space */
     unsigned           RetLab;         /* Return code label */
+    int                        TopLevelSP;     /* SP at function top level */
 };
 
 /* Pointer to current function */
@@ -90,9 +90,9 @@ static Function* NewFunction (struct SymEntry* Sym)
     F->FuncEntry  = Sym;
     F->ReturnType = Sym->Type + 1 + DECODE_SIZE;
     F->Desc      = (FuncDesc*) DecodePtr (Sym->Type + 1);
-    F->EntryCode  = 0;
     F->Reserved          = 0;
     F->RetLab    = GetLabel ();
+    F->TopLevelSP = 0;
 
     /* Return the new structure */
     return F;
@@ -156,18 +156,18 @@ int IsVariadic (const Function* F)
 
 
 
-void RememberEntry (Function* F)
-/* Remember the current output position for local space creation later */
+unsigned GetRetLab (const Function* F)
+/* Return the return jump label */
 {
-    F->EntryCode = GetCodePos ();
+    return F->RetLab;
 }
 
 
 
-unsigned GetRetLab (const Function* F)
-/* Return the return jump label */
+int GetTopLevelSP (const Function* F)
+/* Get the value of the stack pointer on function top level */
 {
-    return F->RetLab;
+    return F->TopLevelSP;
 }
 
 
@@ -215,7 +215,8 @@ void AllocLocalSpace (Function* F)
 void NewFunc (SymEntry* Func)
 /* Parse argument declarations and function body. */
 {
-    int isbrk;
+    int HadReturn;
+    int IsVoidFunc;
     unsigned Flags;
 
     /* Get the function descriptor from the function entry */
@@ -244,11 +245,6 @@ void NewFunc (SymEntry* Func)
     /* Function body now defined */
     Func->Flags |= SC_DEF;
 
-    /* Need a starting curly brace */
-    if (curtok != TOK_LCURLY) {
-       Error ("`{' expected");
-    }
-
     /* Setup register variables */
     InitRegVars ();
 
@@ -264,7 +260,7 @@ void NewFunc (SymEntry* Func)
 
        /* Fastcall functions may never have an ellipsis or the compiler is buggy */
        CHECK ((D->Flags & FD_VARIADIC) == 0);
-                                     
+
        /* Get a pointer to the last parameter entry */
        LastParam = D->SymTab->SymTail;
 
@@ -286,30 +282,56 @@ void NewFunc (SymEntry* Func)
     /* Generate function entry code if needed */
     g_enter (TypeOf (Func->Type), GetParamSize (CurrentFunc));
 
-    /* Remember the current code position. This may be used later to create
-     * local variable space once we have created the function body itself.
-     * Currently this is not possible because the stack offsets of all locals
-     * have to be known in advance.
-     */
-    RememberEntry (CurrentFunc);
-
-    /* Parse the function body */
+    /* Setup the stack */
     oursp = 0;
-    isbrk = compound ();
 
-    /* If the function did not end with an return statement, create exit code */
-    if (!isbrk) {
-#if 0
-       /* If the function has a return type, flag an error */
-       if (!voidfunc) {
-           Error ("Function `%s' must return a value", Func->Name);
+    /* Need a starting curly brace */
+    ConsumeLCurly ();
+
+    /* Parse local variable declarations if any */
+    DeclareLocals ();
+
+    /* Remember the current stack pointer. All variables allocated elsewhere
+     * must be dropped when doing a return from an inner block.
+     */
+    CurrentFunc->TopLevelSP = oursp;
+
+    /* Now process statements in this block */
+    HadReturn = 0;
+    while (curtok != TOK_RCURLY) {
+       if (curtok != TOK_CEOF) {
+           HadReturn = Statement ();
+       } else {
+           break;
        }
-#endif
-       RestoreRegVars (0);
+    }
 
-       Flags = HasVoidReturn (CurrentFunc)? CF_NONE : CF_REG;
-        g_leave (Flags, 0);
+    /* If the function has a return type but no return statement, flag
+     * a warning
+     */
+    IsVoidFunc = HasVoidReturn (CurrentFunc);
+#if 0
+    /* Does not work reliably */
+    if (!IsVoidFunc && !HadReturn) {
+       Warning ("Function `%s' should return a value", Func->Name);
     }
+#endif
+
+    /* Output the function exit code label */
+    g_defloclabel (GetRetLab (CurrentFunc));
+
+    /* Restore the register variables */
+    RestoreRegVars (!IsVoidFunc);
+
+    /* Generate the exit code */
+    Flags = IsVoidFunc? CF_NONE : CF_REG;
+    g_leave (Flags, 0);
+
+    /* Eat the closing brace */
+    ConsumeRCurly ();
+
+    /* Emit references to imports/exports */
+    EmitExternals ();
 
     /* Dump literal data created by the function */
     DumpLiteralPool ();
index b54671c3c6a1b8079728ace37206822f59767206..f7563e3f2780cfd66f97b0d6138d886a74759ee8 100644 (file)
@@ -76,12 +76,12 @@ int HasVoidReturn (const Function* F);
 int IsVariadic (const Function* F);
 /* Return true if this is a variadic function */
 
-void RememberEntry (Function* F);
-/* Remember the current output position for local space creation later */
-
 unsigned GetRetLab (const Function* F);
 /* Return the return jump label */
 
+int GetTopLevelSP (const Function* F);
+/* Get the value of the stack pointer on function top level */
+
 int ReserveLocalSpace (Function* F, unsigned Size);
 /* Reserve (but don't allocate) the given local space and return the stack
  * offset.
index 833d49c70c644cad41f0db0751b6b1f5607fa1cd..d3479ab1f127aa9b934418950db32a2f9a9b28ff 100644 (file)
 
 
 
-static int statement (void);
-/* Forward decl */
-
-
-
 static int doif (void)
 /* Handle 'if' statement here */
 {
@@ -71,7 +66,7 @@ static int doif (void)
     test (flab1, 0);
 
     /* Parse the if body */
-    gotbreak = statement ();
+    gotbreak = Statement ();
 
     /* Else clause present? */
     if (curtok != TOK_ELSE) {
@@ -99,7 +94,7 @@ static int doif (void)
            flab2 = 0;
        }
        g_defloclabel (flab1);
-       gotbreak &= statement ();
+       gotbreak &= Statement ();
 
        /* Generate the label for the else clause */
        if (flab2) {
@@ -142,7 +137,7 @@ static void dowhile (char wtype)
            g_truejump (CF_NONE, loop);
        } else {
            /* There is code inside the while loop */
-           statement ();
+           Statement ();
            g_jump (loop);
            g_defloclabel (lab);
        }
@@ -150,7 +145,7 @@ static void dowhile (char wtype)
     } else {
 
        /* Do loop */
-               statement ();
+               Statement ();
        Consume (TOK_WHILE, "`while' expected");
        test (loop, 1);
        ConsumeSemi ();
@@ -162,36 +157,33 @@ static void dowhile (char wtype)
 
 
 
-static void doreturn (void)
+static void DoReturn (void)
 /* Handle 'return' statement here */
 {
     struct expent lval;
-    unsigned Flags = 0;                /* Code generator flags */
-    int HaveVal = 0;           /* Do we have a return value in ax? */
-
 
     NextToken ();
     if (curtok != TOK_SEMI) {
                if (HasVoidReturn (CurrentFunc)) {
                    Error ("Returning a value in function with return type void");
                }
-               if (evalexpr (CF_NONE, hie0, &lval) == 0) {
-                   /* Constant value */
-                   Flags = CF_CONST;
-               } else {
-           /* Value in the primary register */
-           HaveVal = 1;
-       }
+
+       /* Evaluate the return expression. Result will be in primary */
+       expression (&lval);
 
        /* Convert the return value to the type of the function result */
        if (!HasVoidReturn (CurrentFunc)) {
-                   Flags |= (assignadjust (GetReturnType (CurrentFunc), &lval) & ~CF_CONST) | CF_REG;
+                   assignadjust (GetReturnType (CurrentFunc), &lval);
        }
     } else if (!HasVoidReturn (CurrentFunc)) {
        Error ("Function `%s' must return a value", GetFuncName (CurrentFunc));
     }
-    RestoreRegVars (HaveVal);
-    g_leave (Flags, lval.e_const);
+
+    /* Cleanup the stack in case we're inside a block with locals */
+    g_space (oursp - GetTopLevelSP (CurrentFunc));
+
+    /* Output a jump to the function exit code */
+    g_jump (GetRetLab (CurrentFunc));
 }
 
 
@@ -414,7 +406,7 @@ static void cascadeswitch (struct expent* eval)
 
        /* Parse statements */
        if (curtok != TOK_RCURLY) {
-                   HaveBreak = statement ();
+                   HaveBreak = Statement ();
        }
     }
 
@@ -503,7 +495,7 @@ static void tableswitch (struct expent* eval)
            HaveBreak = 0;
        }
        if (curtok != TOK_RCURLY) {
-           HaveBreak = statement ();
+           HaveBreak = Statement ();
        }
     }
 
@@ -615,7 +607,7 @@ static void dofor (void)
     ConsumeRParen ();
     g_jump (loop);
     g_defloclabel (lstat);
-    statement ();
+    Statement ();
     g_jump (linc);
     g_defloclabel (lab);
     DelLoop ();
@@ -623,9 +615,58 @@ static void dofor (void)
 
 
 
-static int statement (void)
-/* Statement parser. Called whenever syntax requires a statement.
- * This routine performs that statement and returns 1 if it is a branch,
+static int CompoundStatement (void)
+/* Compound statement. Allow any number of statements inside braces. */
+{
+    int isbrk;
+    int oldsp;
+
+    /* eat LCURLY */
+    NextToken ();
+
+    /* Remember the stack at block entry */
+    oldsp = oursp;
+
+    /* Enter a new lexical level */
+    EnterBlockLevel ();
+
+    /* Parse local variable declarations if any */
+    DeclareLocals ();
+
+    /* Now process statements in this block */
+    isbrk = 0;
+    while (curtok != TOK_RCURLY) {
+       if (curtok != TOK_CEOF) {
+           isbrk = Statement ();
+       } else {
+           break;
+       }
+    }
+
+    /* Emit references to imports/exports for this block */
+    EmitExternals ();
+
+    /* Clean up the stack. */
+    if (isbrk) {
+       oursp = oldsp;
+    } else {
+       g_space (oursp - oldsp);
+       oursp = oldsp;
+    }
+
+    /* Leave the lexical level */
+    LeaveBlockLevel ();
+
+    /* Eat closing brace */
+    ConsumeRCurly ();
+
+    return isbrk;
+}
+
+
+
+int Statement (void)
+/* Statement parser. Returns 1 if the statement does a return/break, returns
  * 0 otherwise
  */
 {
@@ -642,10 +683,10 @@ static int statement (void)
        switch (curtok) {
 
            case TOK_LCURLY:
-               return compound ();
+               return CompoundStatement ();
 
            case TOK_IF:
-               return doif ();
+               return doif ();
 
            case TOK_WHILE:
                dowhile ('w');
@@ -660,7 +701,7 @@ static int statement (void)
                break;
 
            case TOK_RETURN:
-               doreturn ();
+               DoReturn ();
                ConsumeSemi ();
                return 1;
 
@@ -704,61 +745,3 @@ static int statement (void)
 
 
 
-int compound (void)
-/* Compound statement.         Allow any number of statements, inside braces. */
-{
-    static unsigned CurrentLevel = 0;
-
-    int isbrk;
-    int oldsp;
-
-    /* eat LCURLY */
-    NextToken ();
-
-    /* Remember the stack at block entry */
-    oldsp = oursp;
-
-    /* If we're not on function level, enter a new lexical level */
-    if (CurrentLevel++ > 0) {
-       /* A nested block */
-       EnterBlockLevel ();
-    }
-
-    /* Parse local variable declarations if any */
-    DeclareLocals ();
-
-    /* Now process statements in the function body */
-    isbrk = 0;
-    while (curtok != TOK_RCURLY) {
-       if (curtok == TOK_CEOF)
-           break;
-       else {
-           isbrk = statement ();
-       }
-    }
-
-    /* Emit references to imports/exports for this block */
-    EmitExternals ();
-
-    /* If this is not the top level compound statement, clean up the stack.
-     * For a top level statement this will be done by the function exit code.
-     */
-    if (--CurrentLevel != 0) {
-       /* Some sort of nested block */
-       LeaveBlockLevel ();
-       if (isbrk) {
-           oursp = oldsp;
-       } else {
-           g_space (oursp - oldsp);
-           oursp = oldsp;
-       }
-    }
-
-    /* Eat closing brace */
-    ConsumeRCurly ();
-
-    return isbrk;
-}
-
-
-
index 70bfa99e3f3ad51859473c6bdf36ad12f9381e4b..258af070786fb6f3874729ba867c80dbc30d7487 100644 (file)
 
 
 
-int compound ();
-/* Compound statement. Allow any number of statements, inside braces. */
+int Statement (void);
+/* Statement parser. Returns 1 if the statement does a return/break, returns
+ * 0 otherwise
+ */