Implement ir_if (for if-statments) and conversion from AST
authorIan Romanick <ian.d.romanick@intel.com>
Mon, 29 Mar 2010 21:11:25 +0000 (14:11 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Mon, 29 Mar 2010 22:17:11 +0000 (15:17 -0700)
The following tests now pass:

    glslparsertest/shaders/if1.frag
    glslparsertest/shaders/if2.frag

The following tests that used to pass now fail.  It appears that most
of these fail because ast_nequal and ast_equal are not converted to HIR.

    shaders/glsl-unused-varying.frag
    shaders/glsl-fs-sqrt-branch.frag

ast.h
ast_to_hir.cpp
ir.h
ir_print_visitor.cpp
ir_print_visitor.h
ir_visitor.h

diff --git a/ast.h b/ast.h
index a158910421d427ae1db1ed2ce86cb0f48d46694c..53b0e4a2b410d80151bb809f15edf754736f990a 100644 (file)
--- 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;
index 7b1db0c4818e38e8575361376d985f593ac281da..0a505bf414648553226ea6c595eec5e417274ac8 100644 (file)
@@ -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 328cd4e4ff532c9b7819b6d4debb859d0ad734dc..83e4f95b0cc17b1f160245308bfeabb131b181c4 100644 (file)
--- 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);
index aeff280cdd9e319dc0f40c4ffb3a714123952eff..e6b24d2d5bce9456d43dc20a7d3b564428fd18e9 100644 (file)
@@ -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");
+}
index 8fd684eb92a7342631621194a97a423ca5a578b3..76d812e19c1abbb12077c7b7f7fd2c38b5ef2681 100644 (file)
@@ -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:
index 76981f7afc1737a8aa0fb367157bbcea7cc2e3b5..521b1c3d8050cc24fc49f6584652f787020d0001 100644 (file)
@@ -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;
    /*@}*/
 };