Generate correct IR for do-while loops
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>
This commit is contained in:
9
ast.h
9
ast.h
@@ -572,6 +572,15 @@ public:
|
|||||||
ast_expression *rest_expression;
|
ast_expression *rest_expression;
|
||||||
|
|
||||||
ast_node *body;
|
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 *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2104,27 +2104,10 @@ ast_selection_statement::hir(exec_list *instructions,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ir_rvalue *
|
void
|
||||||
ast_iteration_statement::hir(exec_list *instructions,
|
ast_iteration_statement::condition_to_hir(ir_loop *stmt,
|
||||||
struct _mesa_glsl_parse_state *state)
|
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) {
|
if (condition != NULL) {
|
||||||
ir_rvalue *const cond =
|
ir_rvalue *const cond =
|
||||||
condition->hir(& stmt->body_instructions, state);
|
condition->hir(& stmt->body_instructions, state);
|
||||||
@@ -2152,6 +2135,31 @@ ast_iteration_statement::hir(exec_list *instructions,
|
|||||||
stmt->body_instructions.push_tail(if_stmt);
|
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) {
|
if (body != NULL) {
|
||||||
ast_node *node = (ast_node *) body;
|
ast_node *node = (ast_node *) body;
|
||||||
@@ -2164,6 +2172,9 @@ ast_iteration_statement::hir(exec_list *instructions,
|
|||||||
if (rest_expression != NULL)
|
if (rest_expression != NULL)
|
||||||
rest_expression->hir(& stmt->body_instructions, state);
|
rest_expression->hir(& stmt->body_instructions, state);
|
||||||
|
|
||||||
|
if (mode == ast_do_while)
|
||||||
|
condition_to_hir(stmt, state);
|
||||||
|
|
||||||
if (mode == ast_for)
|
if (mode == ast_for)
|
||||||
state->symbols->pop_scope();
|
state->symbols->pop_scope();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user