1
0
mirror of https://github.com/cc65/cc65.git synced 2024-09-27 19:55:09 +00:00

Use one function exit point

git-svn-id: svn://svn.cc65.org/cc65/trunk@674 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-03-26 20:07:05 +00:00
parent b0f3e85d44
commit c3ec23aed0
4 changed files with 139 additions and 132 deletions

View File

@ -64,9 +64,9 @@ struct Function {
struct SymEntry* FuncEntry; /* Symbol table entry */ struct SymEntry* FuncEntry; /* Symbol table entry */
type* ReturnType; /* Function return type */ type* ReturnType; /* Function return type */
struct FuncDesc* Desc; /* Function descriptor */ struct FuncDesc* Desc; /* Function descriptor */
CodeMark EntryCode; /* Backpatch addr for entry code */
int Reserved; /* Reserved local space */ int Reserved; /* Reserved local space */
unsigned RetLab; /* Return code label */ unsigned RetLab; /* Return code label */
int TopLevelSP; /* SP at function top level */
}; };
/* Pointer to current function */ /* Pointer to current function */
@ -90,9 +90,9 @@ static Function* NewFunction (struct SymEntry* Sym)
F->FuncEntry = Sym; F->FuncEntry = Sym;
F->ReturnType = Sym->Type + 1 + DECODE_SIZE; F->ReturnType = Sym->Type + 1 + DECODE_SIZE;
F->Desc = (FuncDesc*) DecodePtr (Sym->Type + 1); F->Desc = (FuncDesc*) DecodePtr (Sym->Type + 1);
F->EntryCode = 0;
F->Reserved = 0; F->Reserved = 0;
F->RetLab = GetLabel (); F->RetLab = GetLabel ();
F->TopLevelSP = 0;
/* Return the new structure */ /* Return the new structure */
return F; return F;
@ -156,14 +156,6 @@ int IsVariadic (const Function* F)
void RememberEntry (Function* F)
/* Remember the current output position for local space creation later */
{
F->EntryCode = GetCodePos ();
}
unsigned GetRetLab (const Function* F) unsigned GetRetLab (const Function* F)
/* Return the return jump label */ /* Return the return jump label */
{ {
@ -172,6 +164,14 @@ unsigned GetRetLab (const Function* F)
int GetTopLevelSP (const Function* F)
/* Get the value of the stack pointer on function top level */
{
return F->TopLevelSP;
}
int ReserveLocalSpace (Function* F, unsigned Size) int ReserveLocalSpace (Function* F, unsigned Size)
/* Reserve (but don't allocate) the given local space and return the stack /* Reserve (but don't allocate) the given local space and return the stack
* offset. * offset.
@ -215,7 +215,8 @@ void AllocLocalSpace (Function* F)
void NewFunc (SymEntry* Func) void NewFunc (SymEntry* Func)
/* Parse argument declarations and function body. */ /* Parse argument declarations and function body. */
{ {
int isbrk; int HadReturn;
int IsVoidFunc;
unsigned Flags; unsigned Flags;
/* Get the function descriptor from the function entry */ /* Get the function descriptor from the function entry */
@ -244,11 +245,6 @@ void NewFunc (SymEntry* Func)
/* Function body now defined */ /* Function body now defined */
Func->Flags |= SC_DEF; Func->Flags |= SC_DEF;
/* Need a starting curly brace */
if (curtok != TOK_LCURLY) {
Error ("`{' expected");
}
/* Setup register variables */ /* Setup register variables */
InitRegVars (); InitRegVars ();
@ -264,7 +260,7 @@ void NewFunc (SymEntry* Func)
/* Fastcall functions may never have an ellipsis or the compiler is buggy */ /* Fastcall functions may never have an ellipsis or the compiler is buggy */
CHECK ((D->Flags & FD_VARIADIC) == 0); CHECK ((D->Flags & FD_VARIADIC) == 0);
/* Get a pointer to the last parameter entry */ /* Get a pointer to the last parameter entry */
LastParam = D->SymTab->SymTail; LastParam = D->SymTab->SymTail;
@ -286,31 +282,57 @@ void NewFunc (SymEntry* Func)
/* Generate function entry code if needed */ /* Generate function entry code if needed */
g_enter (TypeOf (Func->Type), GetParamSize (CurrentFunc)); g_enter (TypeOf (Func->Type), GetParamSize (CurrentFunc));
/* Remember the current code position. This may be used later to create /* Setup the stack */
* 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 */
oursp = 0; oursp = 0;
isbrk = compound ();
/* If the function did not end with an return statement, create exit code */ /* Need a starting curly brace */
if (!isbrk) { ConsumeLCurly ();
#if 0
/* If the function has a return type, flag an error */ /* Parse local variable declarations if any */
if (!voidfunc) { DeclareLocals ();
Error ("Function `%s' must return a value", Func->Name);
/* 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 */ /* Dump literal data created by the function */
DumpLiteralPool (); DumpLiteralPool ();

View File

@ -76,12 +76,12 @@ int HasVoidReturn (const Function* F);
int IsVariadic (const Function* F); int IsVariadic (const Function* F);
/* Return true if this is a variadic function */ /* 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); unsigned GetRetLab (const Function* F);
/* Return the return jump label */ /* 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); int ReserveLocalSpace (Function* F, unsigned Size);
/* Reserve (but don't allocate) the given local space and return the stack /* Reserve (but don't allocate) the given local space and return the stack
* offset. * offset.

View File

@ -51,11 +51,6 @@
static int statement (void);
/* Forward decl */
static int doif (void) static int doif (void)
/* Handle 'if' statement here */ /* Handle 'if' statement here */
{ {
@ -71,7 +66,7 @@ static int doif (void)
test (flab1, 0); test (flab1, 0);
/* Parse the if body */ /* Parse the if body */
gotbreak = statement (); gotbreak = Statement ();
/* Else clause present? */ /* Else clause present? */
if (curtok != TOK_ELSE) { if (curtok != TOK_ELSE) {
@ -99,7 +94,7 @@ static int doif (void)
flab2 = 0; flab2 = 0;
} }
g_defloclabel (flab1); g_defloclabel (flab1);
gotbreak &= statement (); gotbreak &= Statement ();
/* Generate the label for the else clause */ /* Generate the label for the else clause */
if (flab2) { if (flab2) {
@ -142,7 +137,7 @@ static void dowhile (char wtype)
g_truejump (CF_NONE, loop); g_truejump (CF_NONE, loop);
} else { } else {
/* There is code inside the while loop */ /* There is code inside the while loop */
statement (); Statement ();
g_jump (loop); g_jump (loop);
g_defloclabel (lab); g_defloclabel (lab);
} }
@ -150,7 +145,7 @@ static void dowhile (char wtype)
} else { } else {
/* Do loop */ /* Do loop */
statement (); Statement ();
Consume (TOK_WHILE, "`while' expected"); Consume (TOK_WHILE, "`while' expected");
test (loop, 1); test (loop, 1);
ConsumeSemi (); ConsumeSemi ();
@ -162,36 +157,33 @@ static void dowhile (char wtype)
static void doreturn (void) static void DoReturn (void)
/* Handle 'return' statement here */ /* Handle 'return' statement here */
{ {
struct expent lval; struct expent lval;
unsigned Flags = 0; /* Code generator flags */
int HaveVal = 0; /* Do we have a return value in ax? */
NextToken (); NextToken ();
if (curtok != TOK_SEMI) { if (curtok != TOK_SEMI) {
if (HasVoidReturn (CurrentFunc)) { if (HasVoidReturn (CurrentFunc)) {
Error ("Returning a value in function with return type void"); Error ("Returning a value in function with return type void");
} }
if (evalexpr (CF_NONE, hie0, &lval) == 0) {
/* Constant value */ /* Evaluate the return expression. Result will be in primary */
Flags = CF_CONST; expression (&lval);
} else {
/* Value in the primary register */
HaveVal = 1;
}
/* Convert the return value to the type of the function result */ /* Convert the return value to the type of the function result */
if (!HasVoidReturn (CurrentFunc)) { if (!HasVoidReturn (CurrentFunc)) {
Flags |= (assignadjust (GetReturnType (CurrentFunc), &lval) & ~CF_CONST) | CF_REG; assignadjust (GetReturnType (CurrentFunc), &lval);
} }
} else if (!HasVoidReturn (CurrentFunc)) { } else if (!HasVoidReturn (CurrentFunc)) {
Error ("Function `%s' must return a value", GetFuncName (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 */ /* Parse statements */
if (curtok != TOK_RCURLY) { if (curtok != TOK_RCURLY) {
HaveBreak = statement (); HaveBreak = Statement ();
} }
} }
@ -503,7 +495,7 @@ static void tableswitch (struct expent* eval)
HaveBreak = 0; HaveBreak = 0;
} }
if (curtok != TOK_RCURLY) { if (curtok != TOK_RCURLY) {
HaveBreak = statement (); HaveBreak = Statement ();
} }
} }
@ -615,7 +607,7 @@ static void dofor (void)
ConsumeRParen (); ConsumeRParen ();
g_jump (loop); g_jump (loop);
g_defloclabel (lstat); g_defloclabel (lstat);
statement (); Statement ();
g_jump (linc); g_jump (linc);
g_defloclabel (lab); g_defloclabel (lab);
DelLoop (); DelLoop ();
@ -623,9 +615,58 @@ static void dofor (void)
static int statement (void) static int CompoundStatement (void)
/* Statement parser. Called whenever syntax requires a statement. /* Compound statement. Allow any number of statements inside braces. */
* This routine performs that statement and returns 1 if it is a branch, {
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 * 0 otherwise
*/ */
{ {
@ -642,10 +683,10 @@ static int statement (void)
switch (curtok) { switch (curtok) {
case TOK_LCURLY: case TOK_LCURLY:
return compound (); return CompoundStatement ();
case TOK_IF: case TOK_IF:
return doif (); return doif ();
case TOK_WHILE: case TOK_WHILE:
dowhile ('w'); dowhile ('w');
@ -660,7 +701,7 @@ static int statement (void)
break; break;
case TOK_RETURN: case TOK_RETURN:
doreturn (); DoReturn ();
ConsumeSemi (); ConsumeSemi ();
return 1; 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;
}

View File

@ -17,8 +17,10 @@
int compound (); int Statement (void);
/* Compound statement. Allow any number of statements, inside braces. */ /* Statement parser. Returns 1 if the statement does a return/break, returns
* 0 otherwise
*/