From 48c647b6bd1c3a04fb3a60a5735312d59f6c77d4 Mon Sep 17 00:00:00 2001 From: uz Date: Sat, 17 Apr 2010 15:19:35 +0000 Subject: [PATCH] Added while loop inversion. git-svn-id: svn://svn.cc65.org/cc65/trunk@4642 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/stmt.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index 1f5a61ea4..5078bfa11 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -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); + + /* 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 (LoopLabel, 1); + + /* Remember the end of the condition evaluation code */ + GetCodePos (&CondCodeEnd); /* Define the head label */ g_defcodelabel (LoopLabel); - /* Test the loop condition */ - TestInParens (BreakLabel, 0); - /* 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);