summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-04-05 16:37:49 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-04-07 11:42:36 -0700
commit9e7d010ee0ed89f1fe07a06a9d9bb22e15106ae2 (patch)
tree4635f70480484425f8f79d10e35738e6b5991f3d
parentf8e31e00b1078dc28187a43a1ab8949e154e7533 (diff)
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
-rw-r--r--ast.h2
-rw-r--r--ast_to_hir.cpp63
2 files changed, 65 insertions, 0 deletions
diff --git a/ast.h b/ast.h
index f73e74906f..ba500dc773 100644
--- a/ast.h
+++ b/ast.h
@@ -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,
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp
index ddeab8db67..08e43a9aa6 100644
--- a/ast_to_hir.cpp
+++ b/ast_to_hir.cpp
@@ -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;
+}