summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ast.h3
-rw-r--r--ast_to_hir.cpp49
-rw-r--r--ir.h22
-rw-r--r--ir_print_visitor.cpp24
-rw-r--r--ir_print_visitor.h1
-rw-r--r--ir_visitor.h1
6 files changed, 100 insertions, 0 deletions
diff --git a/ast.h b/ast.h
index a158910421..53b0e4a2b4 100644
--- a/ast.h
+++ b/ast.h
@@ -492,6 +492,9 @@ public:
ast_node *else_statement);
virtual void print(void) const;
+ virtual ir_rvalue *hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state);
+
ast_expression *condition;
ast_node *then_statement;
ast_node *else_statement;
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp
index 7b1db0c481..0a505bf414 100644
--- a/ast_to_hir.cpp
+++ b/ast_to_hir.cpp
@@ -1318,3 +1318,52 @@ ast_jump_statement::hir(exec_list *instructions,
*/
return NULL;
}
+
+
+ir_rvalue *
+ast_selection_statement::hir(exec_list *instructions,
+ struct _mesa_glsl_parse_state *state)
+{
+ ir_rvalue *const condition = this->condition->hir(instructions, state);
+ struct simple_node *ptr;
+
+ /* From page 66 (page 72 of the PDF) of the GLSL 1.50 spec:
+ *
+ * "Any expression whose type evaluates to a Boolean can be used as the
+ * conditional expression bool-expression. Vector types are not accepted
+ * as the expression to if."
+ *
+ * The checks are separated so that higher quality diagnostics can be
+ * generated for cases where both rules are violated.
+ */
+ if (!condition->type->is_boolean() || !condition->type->is_scalar()) {
+ YYLTYPE loc = this->condition->get_location();
+
+ _mesa_glsl_error(& loc, state, "if-statement condition must be scalar "
+ "boolean");
+ }
+
+ ir_if *const stmt = new ir_if(condition);
+
+ if (then_statement != NULL) {
+ ast_node *node = (ast_node *) then_statement;
+ do {
+ node->hir(& stmt->then_instructions, state);
+ node = (ast_node *) node->next;
+ } while (node != then_statement);
+ }
+
+ if (else_statement != NULL) {
+ ast_node *node = (ast_node *) else_statement;
+ do {
+ node->hir(& stmt->else_instructions, state);
+ node = (ast_node *) node->next;
+ } while (node != else_statement);
+ }
+
+ instructions->push_tail(stmt);
+
+ /* if-statements do not have r-values.
+ */
+ return NULL;
+}
diff --git a/ir.h b/ir.h
index 328cd4e4ff..83e4f95b0c 100644
--- a/ir.h
+++ b/ir.h
@@ -192,6 +192,28 @@ public:
/*@}*/
+/**
+ * IR instruction representing high-level if-statements
+ */
+class ir_if : public ir_instruction {
+public:
+ ir_if(ir_rvalue *condition)
+ : condition(condition)
+ {
+ /* empty */
+ }
+
+ virtual void accept(ir_visitor *v)
+ {
+ v->visit(this);
+ }
+
+ ir_rvalue *condition;
+ exec_list then_instructions;
+ exec_list else_instructions;
+};
+
+
class ir_assignment : public ir_rvalue {
public:
ir_assignment(ir_rvalue *lhs, ir_rvalue *rhs, ir_rvalue *condition);
diff --git a/ir_print_visitor.cpp b/ir_print_visitor.cpp
index aeff280cdd..e6b24d2d5b 100644
--- a/ir_print_visitor.cpp
+++ b/ir_print_visitor.cpp
@@ -265,3 +265,27 @@ ir_print_visitor::visit(ir_return *ir)
printf(")");
}
+
+
+void
+ir_print_visitor::visit(ir_if *ir)
+{
+ printf("(if ");
+ ir->condition->accept(this);
+
+ printf("(\n");
+ foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ inst->accept(this);
+ }
+ printf(")\n");
+
+ printf("(\n");
+ foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
+ ir_instruction *const inst = (ir_instruction *) iter.get();
+
+ inst->accept(this);
+ }
+ printf("))\n");
+}
diff --git a/ir_print_visitor.h b/ir_print_visitor.h
index 8fd684eb92..76d812e19c 100644
--- a/ir_print_visitor.h
+++ b/ir_print_visitor.h
@@ -64,6 +64,7 @@ public:
virtual void visit(ir_constant *);
virtual void visit(ir_call *);
virtual void visit(ir_return *);
+ virtual void visit(ir_if *);
/*@}*/
private:
diff --git a/ir_visitor.h b/ir_visitor.h
index 76981f7afc..521b1c3d80 100644
--- a/ir_visitor.h
+++ b/ir_visitor.h
@@ -55,6 +55,7 @@ public:
virtual void visit(class ir_constant *) = 0;
virtual void visit(class ir_call *) = 0;
virtual void visit(class ir_return *) = 0;
+ virtual void visit(class ir_if *) = 0;
/*@}*/
};