X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fstmt.c;h=5078bfa11a1d32c4076e304247fd1b2d1bcde8cb;hb=112ae0e3db511ddd92e769c11328646ebe2a6240;hp=b9b258aa09e365741b5263cf3d1e24d9e1715dfe;hpb=0a9c7484ad7299f2189e42f6e300f6cd3ab4c334;p=cc65 diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index b9b258aa0..5078bfa11 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -91,7 +91,7 @@ static void CheckTok (token_t Tok, const char* Msg, int* PendingToken) */ { if (CurTok.Tok != Tok) { - Error (Msg); + Error ("%s", Msg); } else if (PendingToken) { *PendingToken = 1; } else { @@ -244,31 +244,50 @@ static void DoStatement (void) static void WhileStatement (void) /* Handle the 'while' statement */ { - int PendingToken; + int PendingToken; + CodeMark CondCodeStart; /* Start of condition evaluation code */ + CodeMark CondCodeEnd; /* End of condition evaluation code */ + CodeMark Here; /* "Here" location of code */ /* Get the loop control labels */ unsigned LoopLabel = GetLocalLabel (); unsigned BreakLabel = GetLocalLabel (); + unsigned CondLabel = GetLocalLabel (); /* Skip the while token */ NextToken (); - /* Add the loop to the loop stack. In case of a while loop, the loop head + /* Add the loop to the loop stack. In case of a while loop, the condition * label is used for continue statements. */ - AddLoop (BreakLabel, LoopLabel); + AddLoop (BreakLabel, CondLabel); - /* Define the head label */ - g_defcodelabel (LoopLabel); + /* We will move the code that evaluates the while condition to the end of + * the loop, so generate a jump here. + */ + g_jump (CondLabel); + + /* Remember the current position */ + GetCodePos (&CondCodeStart); + + /* Emit the code position label */ + g_defcodelabel (CondLabel); /* Test the loop condition */ - TestInParens (BreakLabel, 0); + TestInParens (LoopLabel, 1); + + /* Remember the end of the condition evaluation code */ + GetCodePos (&CondCodeEnd); + + /* Define the head label */ + g_defcodelabel (LoopLabel); /* Loop body */ Statement (&PendingToken); - /* Jump back to loop top */ - g_jump (LoopLabel); + /* Move the test code here */ + GetCodePos (&Here); + MoveCode (&CondCodeStart, &CondCodeEnd, &Here); /* Exit label */ g_defcodelabel (BreakLabel); @@ -314,7 +333,7 @@ static void ReturnStatement (void) } /* Mark the function as having a return statement */ - F_HasReturn (CurrentFunc); + F_ReturnFound (CurrentFunc); /* Cleanup the stack in case we're inside a block with locals */ g_space (StackPtr - F_GetTopLevelSP (CurrentFunc)); @@ -544,101 +563,100 @@ int Statement (int* PendingToken) *PendingToken = 0; } - /* Check for a label */ - if (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { - - /* Special handling for a label */ + /* Check for a label. A label is always part of a statement, it does not + * replace one. + */ + while (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) { + /* Handle the label */ DoLabel (); CheckLabelWithoutStatement (); + } - } else { + switch (CurTok.Tok) { - switch (CurTok.Tok) { - - case TOK_LCURLY: - NextToken (); - GotBreak = CompoundStatement (); - CheckTok (TOK_RCURLY, "`{' expected", PendingToken); - return GotBreak; - - case TOK_IF: - return IfStatement (); - - case TOK_WHILE: - WhileStatement (); - break; - - case TOK_DO: - DoStatement (); - break; - - case TOK_SWITCH: - SwitchStatement (); - break; - - case TOK_RETURN: - ReturnStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_BREAK: - BreakStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_CONTINUE: - ContinueStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_FOR: - ForStatement (); - break; - - case TOK_GOTO: - GotoStatement (); - CheckSemi (PendingToken); - return 1; - - case TOK_SEMI: - /* Ignore it */ - CheckSemi (PendingToken); - break; - - case TOK_PRAGMA: - DoPragma (); - break; - - case TOK_CASE: - CaseLabel (); - CheckLabelWithoutStatement (); - break; - - case TOK_DEFAULT: - DefaultLabel (); - CheckLabelWithoutStatement (); - break; - - default: - /* Remember the current code position */ - GetCodePos (&Start); - /* Actual statement */ - ExprWithCheck (hie0, &Expr); - /* Load the result only if it is an lvalue and the type is - * marked as volatile. Otherwise the load is useless. - */ - if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) { - LoadExpr (CF_NONE, &Expr); - } - /* If the statement didn't generate code, and is not of type - * void, emit a warning. - */ - GetCodePos (&End); - if (CodeRangeIsEmpty (&Start, &End) && !IsTypeVoid (Expr.Type)) { - Warning ("Statement has no effect"); - } - CheckSemi (PendingToken); - } + case TOK_LCURLY: + NextToken (); + GotBreak = CompoundStatement (); + CheckTok (TOK_RCURLY, "`{' expected", PendingToken); + return GotBreak; + + case TOK_IF: + return IfStatement (); + + case TOK_WHILE: + WhileStatement (); + break; + + case TOK_DO: + DoStatement (); + break; + + case TOK_SWITCH: + SwitchStatement (); + break; + + case TOK_RETURN: + ReturnStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_BREAK: + BreakStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_CONTINUE: + ContinueStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_FOR: + ForStatement (); + break; + + case TOK_GOTO: + GotoStatement (); + CheckSemi (PendingToken); + return 1; + + case TOK_SEMI: + /* Ignore it */ + CheckSemi (PendingToken); + break; + + case TOK_PRAGMA: + DoPragma (); + break; + + case TOK_CASE: + CaseLabel (); + CheckLabelWithoutStatement (); + break; + + case TOK_DEFAULT: + DefaultLabel (); + CheckLabelWithoutStatement (); + break; + + default: + /* Remember the current code position */ + GetCodePos (&Start); + /* Actual statement */ + ExprWithCheck (hie0, &Expr); + /* Load the result only if it is an lvalue and the type is + * marked as volatile. Otherwise the load is useless. + */ + if (ED_IsLVal (&Expr) && IsQualVolatile (Expr.Type)) { + LoadExpr (CF_NONE, &Expr); + } + /* If the statement didn't generate code, and is not of type + * void, emit a warning. + */ + GetCodePos (&End); + if (CodeRangeIsEmpty (&Start, &End) && !IsTypeVoid (Expr.Type)) { + Warning ("Statement has no effect"); + } + CheckSemi (PendingToken); } return 0; }