1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-09 06:29:38 +00:00

Optimizer bugfixes, polished the line info.

git-svn-id: svn://svn.cc65.org/cc65/trunk@761 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-05-26 10:58:40 +00:00
parent 916a0879d5
commit 034a4b75e5
4 changed files with 100 additions and 28 deletions

View File

@ -499,7 +499,7 @@ static unsigned OptSub2 (CodeSeg* S)
CodeEntry* E = GetCodeEntry (S, I);
/* Check for the sequence */
if (E->OPC == OPC_LDA &&
if (E->OPC == OPC_LDA &&
GetCodeEntries (S, L, I+1, 5) &&
L[0]->OPC == OPC_SEC &&
!CodeEntryHasLabel (L[0]) &&
@ -527,8 +527,15 @@ static unsigned OptSub2 (CodeSeg* S)
MoveCodeEntry (S, I, I+3);
ReplaceOPC (E, OPC_SBC);
/* If the sequence head had a label, move this label back to the
* head.
*/
if (CodeEntryHasLabel (E)) {
MoveCodeLabels (S, E, L[0]);
}
/* Remember, we had changes */
++Changes;
++Changes;
}
@ -765,6 +772,13 @@ static unsigned OptCmp3 (CodeSeg* S)
ReplaceOPC (L[0], OPC_LDA);
ReplaceOPC (L[1], OPC_CMP);
/* Beware: If the first LDA instruction had a label, we have
* to move this label to the top of the sequence again.
*/
if (CodeEntryHasLabel (E)) {
MoveCodeLabels (S, E, L[0]);
}
}
++Changes;

View File

@ -296,7 +296,7 @@ void NewFunc (SymEntry* Func)
HadReturn = 0;
while (CurTok.Tok != TOK_RCURLY) {
if (CurTok.Tok != TOK_CEOF) {
HadReturn = Statement ();
HadReturn = Statement (0);
} else {
break;
}

View File

@ -46,11 +46,48 @@
/*****************************************************************************/
/* Forwards */
/* Helper functions */
/*****************************************************************************/
static void CheckTok (token_t Tok, const char* Msg, int* PendingToken)
/* Helper function for Statement. Will check for Tok and print Msg if not
* found. If PendingToken is NULL, it will the skip the token, otherwise
* it will store one to PendingToken.
*/
{
if (CurTok.Tok != Tok) {
Error (Msg);
} else if (PendingToken) {
*PendingToken = 1;
} else {
NextToken ();
}
}
static void CheckSemi (int* PendingToken)
/* Helper function for Statement. Will call CheckTok with the parameters
* for a semicolon.
*/
{
CheckTok (TOK_SEMI, "`;' expected", PendingToken);
}
static void SkipPending (int PendingToken)
/* Skip the pending token if we have one */
{
if (PendingToken) {
NextToken ();
}
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@ -71,12 +108,13 @@ static int IfStatement (void)
test (Label1, 0);
/* Parse the if body */
GotBreak = Statement ();
GotBreak = Statement (0);
/* Else clause present? */
if (CurTok.Tok != TOK_ELSE) {
g_defcodelabel (Label1);
/* Since there's no else clause, we're not sure, if the a break
* statement is really executed.
*/
@ -95,7 +133,7 @@ static int IfStatement (void)
g_defcodelabel (Label1);
/* Total break only if both branches had a break. */
GotBreak &= Statement ();
GotBreak &= Statement (0);
/* Generate the label for the else clause */
g_defcodelabel (Label2);
@ -124,7 +162,7 @@ static void DoStatement (void)
g_defcodelabel (loop);
/* Parse the loop body */
Statement ();
Statement (0);
/* Parse the end condition */
Consume (TOK_WHILE, "`while' expected");
@ -143,6 +181,8 @@ static void DoStatement (void)
static void WhileStatement (void)
/* Handle the 'while' statement */
{
int PendingToken;
/* Get the loop control labels */
unsigned loop = GetLocalLabel ();
unsigned lab = GetLocalLabel ();
@ -172,9 +212,10 @@ static void WhileStatement (void)
NextToken ();
} else {
/* There is code inside the while loop, parse the body */
Statement ();
Statement (&PendingToken);
g_jump (loop);
g_defcodelabel (lab);
SkipPending (PendingToken);
}
/* Remove the loop from the loop stack */
@ -432,7 +473,7 @@ static void CascadeSwitch (struct expent* eval)
/* Parse statements */
if (CurTok.Tok != TOK_RCURLY) {
HaveBreak = Statement ();
HaveBreak = Statement (0);
}
}
@ -521,7 +562,7 @@ static void TableSwitch (struct expent* eval)
HaveBreak = 0;
}
if (CurTok.Tok != TOK_RCURLY) {
HaveBreak = Statement ();
HaveBreak = Statement (0);
}
}
@ -600,6 +641,7 @@ static void ForStatement (void)
struct expent lval1;
struct expent lval2;
struct expent lval3;
int PendingToken;
/* Get several local labels needed later */
unsigned TestLabel = GetLocalLabel ();
@ -651,10 +693,13 @@ static void ForStatement (void)
/* Loop body */
g_defcodelabel (lstat);
Statement ();
Statement (&PendingToken);
/* Jump back to the increment expression */
g_jump (IncLabel);
/* Skip a pending token if we have one */
SkipPending (PendingToken);
/* Declare the break label */
g_defcodelabel (lab);
@ -678,9 +723,6 @@ static int CompoundStatement (void)
/* Enter a new lexical level */
EnterBlockLevel ();
/* Skip the rcurly */
NextToken ();
/* Parse local variable declarations if any */
DeclareLocals ();
@ -688,7 +730,7 @@ static int CompoundStatement (void)
GotBreak = 0;
while (CurTok.Tok != TOK_RCURLY) {
if (CurTok.Tok != TOK_CEOF) {
GotBreak = Statement ();
GotBreak = Statement (0);
} else {
break;
}
@ -700,9 +742,6 @@ static int CompoundStatement (void)
}
oursp = OldStack;
/* Skip the closing brace */
ConsumeRCurly ();
/* Emit references to imports/exports for this block */
EmitExternals ();
@ -714,12 +753,23 @@ static int CompoundStatement (void)
int Statement (void)
int Statement (int* PendingToken)
/* Statement parser. Returns 1 if the statement does a return/break, returns
* 0 otherwise
* 0 otherwise. If the PendingToken pointer is not NULL, the function will
* not skip the terminating token of the statement (closing brace or
* semicolon), but store true if there is a pending token, and false if there
* is none. The token is always checked, so there is no need for the caller to
* check this token, it must be skipped, however. If the argument pointer is
* NULL, the function will skip the token.
*/
{
struct expent lval;
int GotBreak;
/* Assume no pending token */
if (PendingToken) {
*PendingToken = 0;
}
/* Check for a label */
if (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) {
@ -732,7 +782,10 @@ int Statement (void)
switch (CurTok.Tok) {
case TOK_LCURLY:
return CompoundStatement ();
NextToken ();
GotBreak = CompoundStatement ();
CheckTok (TOK_RCURLY, "`{' expected", PendingToken);
return GotBreak;
case TOK_IF:
return IfStatement ();
@ -751,17 +804,17 @@ int Statement (void)
case TOK_RETURN:
ReturnStatement ();
ConsumeSemi ();
CheckSemi (PendingToken);
return 1;
case TOK_BREAK:
BreakStatement ();
ConsumeSemi ();
CheckSemi (PendingToken);
return 1;
case TOK_CONTINUE:
ContinueStatement ();
ConsumeSemi ();
CheckSemi (PendingToken);
return 1;
case TOK_FOR:
@ -770,7 +823,7 @@ int Statement (void)
case TOK_GOTO:
GotoStatement ();
ConsumeSemi ();
CheckSemi (PendingToken);
return 1;
case TOK_SEMI:
@ -785,7 +838,7 @@ int Statement (void)
default:
/* Actual statement */
expression (&lval);
ConsumeSemi ();
CheckSemi (PendingToken);
}
}
return 0;

View File

@ -17,9 +17,14 @@
int Statement (void);
int Statement (int* PendingToken);
/* Statement parser. Returns 1 if the statement does a return/break, returns
* 0 otherwise
* 0 otherwise. If the PendingToken pointer is not NULL, the function will
* not skip the terminating token of the statement (closing brace or
* semicolon), but store true if there is a pending token, and false if there
* is none. The token is always checked, so there is no need for the caller to
* check this token, it must be skipped, however. If the argument pointer is
* NULL, the function will skip the token.
*/