Generate correct IR for do-while loops
authorIan Romanick <ian.d.romanick@intel.com>
Tue, 6 Apr 2010 01:07:27 +0000 (18:07 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Wed, 7 Apr 2010 18:42:36 +0000 (11:42 -0700)
Previously the same code was generated for a while loop and a do-while
loop.  This pulls the code that generates the conditional break into a
separate method.  This method is called either at the beginning or the
end depending on the loop type.

Reported-by: Kenneth Graunke <kenneth@whitecape.org>
ast.h
ast_to_hir.cpp

diff --git a/ast.h b/ast.h
index ba500dc..d899fb1 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -572,6 +572,15 @@ public:
    ast_expression *rest_expression;
 
    ast_node *body;
+
+private:
+   /**
+    * Generate IR from the condition of a loop
+    *
+    * This is factored out of ::hir because some loops have the condition
+    * test at the top (for and while), and others have it at the end (do-while).
+    */
+   void condition_to_hir(class ir_loop *, struct _mesa_glsl_parse_state *);
 };
 
 
index ae5a8d5..6afd7ea 100644 (file)
@@ -2104,27 +2104,10 @@ ast_selection_statement::hir(exec_list *instructions,
 }
 
 
-ir_rvalue *
-ast_iteration_statement::hir(exec_list *instructions,
-                            struct _mesa_glsl_parse_state *state)
+void
+ast_iteration_statement::condition_to_hir(ir_loop *stmt,
+                                         struct _mesa_glsl_parse_state *state)
 {
-   /* For loops start a new scope, but while and do-while loops do not.
-    */
-   if (mode == ast_for)
-      state->symbols->push_scope();
-
-   if (init_statement != NULL)
-      init_statement->hir(instructions, state);
-
-   ir_loop *const stmt = new ir_loop();
-   instructions->push_tail(stmt);
-
-   /* Track the current loop and / or switch-statement nesting.
-    */
-   ir_instruction *const nesting = state->loop_or_switch_nesting;
-   state->loop_or_switch_nesting = stmt;
-
-
    if (condition != NULL) {
       ir_rvalue *const cond =
         condition->hir(& stmt->body_instructions, state);
@@ -2152,6 +2135,31 @@ ast_iteration_statement::hir(exec_list *instructions,
         stmt->body_instructions.push_tail(if_stmt);
       }
    }
+}
+
+
+ir_rvalue *
+ast_iteration_statement::hir(exec_list *instructions,
+                            struct _mesa_glsl_parse_state *state)
+{
+   /* For loops start a new scope, but while and do-while loops do not.
+    */
+   if (mode == ast_for)
+      state->symbols->push_scope();
+
+   if (init_statement != NULL)
+      init_statement->hir(instructions, state);
+
+   ir_loop *const stmt = new ir_loop();
+   instructions->push_tail(stmt);
+
+   /* Track the current loop and / or switch-statement nesting.
+    */
+   ir_instruction *const nesting = state->loop_or_switch_nesting;
+   state->loop_or_switch_nesting = stmt;
+
+   if (mode != ast_do_while)
+      condition_to_hir(stmt, state);
 
    if (body != NULL) {
       ast_node *node = (ast_node *) body;
@@ -2164,6 +2172,9 @@ ast_iteration_statement::hir(exec_list *instructions,
    if (rest_expression != NULL)
       rest_expression->hir(& stmt->body_instructions, state);
 
+   if (mode == ast_do_while)
+      condition_to_hir(stmt, state);
+
    if (mode == ast_for)
       state->symbols->pop_scope();