From: cuz Date: Mon, 26 Mar 2001 20:07:05 +0000 (+0000) Subject: Use one function exit point X-Git-Tag: V2.12.0~2888 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=c3ec23aed0377bf7b6a4449289535a6e33ce6994;p=cc65 Use one function exit point git-svn-id: svn://svn.cc65.org/cc65/trunk@674 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/cc65/function.c b/src/cc65/function.c index d9efc9a77..b4340b85e 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -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 (); diff --git a/src/cc65/function.h b/src/cc65/function.h index b54671c3c..f7563e3f2 100644 --- a/src/cc65/function.h +++ b/src/cc65/function.h @@ -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. diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index 833d49c70..d3479ab1f 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -51,11 +51,6 @@ -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; -} - - - diff --git a/src/cc65/stmt.h b/src/cc65/stmt.h index 70bfa99e3..258af0707 100644 --- a/src/cc65/stmt.h +++ b/src/cc65/stmt.h @@ -17,8 +17,10 @@ -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 + */