From c8171988a2d994f4dd25de0e3d66cdb7cb390100 Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 4 Dec 2000 22:28:15 +0000 Subject: [PATCH] Added new code hints for use at the end of a function git-svn-id: svn://svn.cc65.org/cc65/trunk@552 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codegen.c | 13 +++++- src/cc65/function.c | 5 +- src/cc65/optimize.c | 109 +++++++++++++++++++++++++++----------------- src/cc65/stmt.c | 24 +++++----- 4 files changed, 94 insertions(+), 57 deletions(-) diff --git a/src/cc65/codegen.c b/src/cc65/codegen.c index 3d1bd3ffd..3afcc25b2 100644 --- a/src/cc65/codegen.c +++ b/src/cc65/codegen.c @@ -485,6 +485,12 @@ void g_leave (int flags, int val) int k; char buf [40]; + /* CF_REG is set if we're returning a value from the function */ + if ((flags & CF_REG) == 0) { + AddCodeHint ("x:-"); + AddCodeHint ("a:-"); + } + /* How many bytes of locals do we have to drop? */ k = -oursp; @@ -499,8 +505,10 @@ void g_leave (int flags, int val) /* Drop stackframe or leave with rts */ k += funcargs; if (k == 0) { + AddCodeHint ("y:-"); /* Y register no longer used */ AddCodeLine ("\trts"); } else if (k <= 8) { + AddCodeHint ("y:-"); /* Y register no longer used */ AddCodeLine ("\tjmp\tincsp%d", k); } else { CheckLocalOffs (k); @@ -515,7 +523,10 @@ void g_leave (int flags, int val) /* We've a stack frame to drop */ ldyconst (k); strcat (buf, "y"); - } + } else { + /* Y register no longer used */ + AddCodeHint ("y:-"); + } if (flags & CF_CONST) { if ((flags & CF_TYPE) != CF_LONG) { /* Constant int sized value given for return code */ diff --git a/src/cc65/function.c b/src/cc65/function.c index 91888fabf..393679b77 100644 --- a/src/cc65/function.c +++ b/src/cc65/function.c @@ -198,6 +198,7 @@ void NewFunc (SymEntry* Func) /* Parse argument declarations and function body. */ { int isbrk; + unsigned Flags; /* Get the function descriptor from the function entry */ FuncDesc* D = DecodePtr (Func->Type+1); @@ -251,7 +252,9 @@ void NewFunc (SymEntry* Func) } #endif RestoreRegVars (0); - g_leave (CF_NONE, 0); + + Flags = HasVoidReturn (CurrentFunc)? CF_NONE : CF_REG; + g_leave (Flags, 0); } /* Dump literal data created by the function */ diff --git a/src/cc65/optimize.c b/src/cc65/optimize.c index ed4dc334a..1cb57894b 100644 --- a/src/cc65/optimize.c +++ b/src/cc65/optimize.c @@ -461,7 +461,7 @@ static void FreeLines (Line* Start, Line* End) /*****************************************************************************/ -/* Line Collections */ +/* Line Collections */ /*****************************************************************************/ @@ -536,6 +536,14 @@ static int IsLocalLabel (const Line* L) +static int IsExtLabel (const Line* L) +/* Return true if the line is an external label line */ +{ + return (L->Line [0] == '_'); +} + + + static int IsLabel (const Line* L) /* Return true if the line is a label line */ { @@ -1136,13 +1144,15 @@ static unsigned RVUInt2 (Line* L, L = GetTargetLine (L->Line+5); } - /* Get the next instruction line */ - L = NextInstruction (L); + /* Get the next line, skip local labels */ + do { + L = NextCodeSegLine (L); + } while (L && (IsLocalLabel (L) || L->Line[0] == '\0')); /* Bail out if we're done */ - if (L == 0 || IsLabel (L)) { - /* Something is wrong */ - return REG_ALL; + if (L == 0 || IsExtLabel (L)) { + /* End of function reached */ + goto ExitPoint; } /* Check if we had this line already. If so, bail out, if not, @@ -1154,55 +1164,68 @@ static unsigned RVUInt2 (Line* L, } while (LineMatch (L, "\tjmp\tL") || LineMatch (L, "\tbra\tL")); + /* Special handling of code hints */ + if (IsHintLine (L)) { + + if (IsHint (L, "a:-") && (Used & REG_A) == 0) { + Unused |= REG_A; + } else if (IsHint (L, "x:-") && (Used & REG_X) == 0) { + Unused |= REG_X; + } else if (IsHint (L, "y:-") && (Used & REG_Y) == 0) { + Unused |= REG_Y; + } + /* Special handling for branches */ - if (LineMatchX (L, ShortBranches) >= 0 || + } else if (LineMatchX (L, ShortBranches) >= 0 || LineMatchX (L, LongBranches) >= 0) { const char* Target = L->Line+5; if (Target[0] == 'L') { - /* Jump to local label. Check the register usage starting at - * the branch target and at the code following the branch. - * All registers that are unused in both execution flows are - * returned as unused. - */ - unsigned U1, U2; + /* Jump to local label. Check the register usage starting at + * the branch target and at the code following the branch. + * All registers that are unused in both execution flows are + * returned as unused. + */ + unsigned U1, U2; U2 = RVUInt1 (GetTargetLine (Target), LC, Used, Unused); - U1 = RVUInt1 (L, LC, Used, Unused); - return U1 | U2; /* Used in any of the branches */ + U1 = RVUInt1 (L, LC, Used, Unused); + return U1 | U2; /* Used in any of the branches */ } - } + } else { - /* Search for the instruction in this line */ - I = FindCmd (L); + /* Search for the instruction in this line */ + I = FindCmd (L); - /* If we don't find it, assume all other registers are */ - if (I < 0) { - break; - } + /* If we don't find it, assume all other registers are used */ + if (I < 0) { + break; + } - /* Evaluate the use flags, check for addressing modes */ - R = CmdDesc[I].Use; - if (IsXAddrMode (L)) { - R |= REG_X; - } else if (IsYAddrMode (L)) { - R |= REG_Y; - } - if (R) { - /* Remove registers that were already new loaded */ - R &= ~Unused; + /* Evaluate the use flags, check for addressing modes */ + R = CmdDesc[I].Use; + if (IsXAddrMode (L)) { + R |= REG_X; + } else if (IsYAddrMode (L)) { + R |= REG_Y; + } + if (R) { + /* Remove registers that were already new loaded */ + R &= ~Unused; - /* Remember the remaining registers */ - Used |= R; - } + /* Remember the remaining registers */ + Used |= R; + } - /* Evaluate the load flags */ - R = CmdDesc[I].Load; - if (R) { - /* Remove registers that were already used */ - R &= ~Used; + /* Evaluate the load flags */ + R = CmdDesc[I].Load; + if (R) { + /* Remove registers that were already used */ + R &= ~Used; - /* Remember the remaining registers */ - Unused |= R; - } + /* Remember the remaining registers */ + Unused |= R; + } + + } /* If we know about all registers, bail out */ if ((Used | Unused) == REG_ALL) { diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index eda5c1433..5a1ec4a9c 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -166,7 +166,7 @@ static void doreturn (void) /* Handle 'return' statement here */ { struct expent lval; - unsigned etype = 0; /* Type of return expression */ + unsigned Flags = 0; /* Code generator flags */ int HaveVal = 0; /* Do we have a return value in ax? */ @@ -177,21 +177,21 @@ static void doreturn (void) } if (evalexpr (CF_NONE, hie0, &lval) == 0) { /* Constant value */ - etype = CF_CONST; + Flags = CF_CONST; } else { - /* Value in the primary register */ - HaveVal = 1; - } + /* Value in the primary register */ + HaveVal = 1; + } - /* Convert the return value to the type of the function result */ - if (!HasVoidReturn (CurrentFunc)) { - etype |= assignadjust (GetReturnType (CurrentFunc), &lval) & ~CF_CONST; - } + /* Convert the return value to the type of the function result */ + if (!HasVoidReturn (CurrentFunc)) { + Flags |= (assignadjust (GetReturnType (CurrentFunc), &lval) & ~CF_CONST) | CF_REG; + } } 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 (etype, lval.e_const); + g_leave (Flags, lval.e_const); } @@ -396,7 +396,7 @@ static void cascadeswitch (struct expent* eval) CodeLab = GetLabel (); } g_jump (CodeLab); - } + } /* Remember that we had a default label */ HaveDefault = 1; -- 2.39.5