Process ast_iteration_statement into ir_loop

This causes the following tests to pass:
     glslparsertest/shaders/dowhile.frag
     glslparsertest/shaders/while.frag
     glslparsertest/shaders/while1.frag
     glslparsertest/shaders/while2.frag
This commit is contained in:
Ian Romanick 2010-04-05 16:37:49 -07:00
parent f8e31e00b1
commit 9e7d010ee0
2 changed files with 65 additions and 0 deletions

2
ast.h
View file

@ -558,6 +558,8 @@ public:
virtual void print(void) const;
virtual ir_rvalue *hir(exec_list *, struct _mesa_glsl_parse_state *);
enum ast_iteration_modes {
ast_for,
ast_while,

View file

@ -2069,3 +2069,66 @@ ast_selection_statement::hir(exec_list *instructions,
*/
return NULL;
}
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);
if (condition != NULL) {
ir_rvalue *const cond =
condition->hir(& stmt->body_instructions, state);
if ((cond == NULL)
|| !cond->type->is_boolean() || !cond->type->is_scalar()) {
YYLTYPE loc = condition->get_location();
_mesa_glsl_error(& loc, state,
"loop condition must be scalar boolean");
} else {
/* As the first code in the loop body, generate a block that looks
* like 'if (!condition) break;' as the loop termination condition.
*/
ir_rvalue *const not_cond =
new ir_expression(ir_unop_logic_not, glsl_type::bool_type, cond,
NULL);
ir_if *const if_stmt = new ir_if(not_cond);
ir_jump *const break_stmt =
new ir_loop_jump(stmt, ir_loop_jump::jump_break);
if_stmt->then_instructions.push_tail(break_stmt);
stmt->body_instructions.push_tail(if_stmt);
}
}
if (body != NULL) {
ast_node *node = (ast_node *) body;
do {
node->hir(& stmt->body_instructions, state);
node = (ast_node *) node->next;
} while (node != body);
}
if (rest_expression != NULL)
rest_expression->hir(& stmt->body_instructions, state);
if (mode == ast_for)
state->symbols->pop_scope();
/* Loops do not have r-values.
*/
return NULL;
}