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
This commit is contained in:
cuz 2000-12-04 22:28:15 +00:00
parent a05a5e5c38
commit c8171988a2
4 changed files with 99 additions and 62 deletions

View file

@ -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 */

View file

@ -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 */

View file

@ -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,56 +1164,69 @@ 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);
/* 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;
/* Remember the remaining registers */
Used |= R;
}
/* Evaluate the load flags */
R = CmdDesc[I].Load;
if (R) {
/* Remove registers that were already used */
R &= ~Used;
/* Remember the remaining registers */
Unused |= R;
}
}
/* 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;
}
/* 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;
}
/* Evaluate the load flags */
R = CmdDesc[I].Load;
if (R) {
/* Remove registers that were already used */
R &= ~Used;
/* Remember the remaining registers */
Unused |= R;
}
/* If we know about all registers, bail out */
if ((Used | Unused) == REG_ALL) {
break;

View file

@ -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;