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_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 *
|
||||
ast_iteration_statement::hir(exec_list *instructions,
|
||||
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();
|
||||
|
||||
|
Reference in New Issue
Block a user