]> git.sur5r.net Git - cc65/commitdiff
Added while loop inversion.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 17 Apr 2010 15:19:35 +0000 (15:19 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Sat, 17 Apr 2010 15:19:35 +0000 (15:19 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@4642 b7a2c559-68d2-44c3-8de9-860c34a00d81

src/cc65/stmt.c

index 1f5a61ea4b785a00c424ff647accdb2debf0bfd7..5078bfa11a1d32c4076e304247fd1b2d1bcde8cb 100644 (file)
@@ -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);