From: Ian Romanick Date: Mon, 29 Mar 2010 21:11:25 +0000 (-0700) Subject: Implement ir_if (for if-statments) and conversion from AST X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3c6fea3048a0d9add2fec621d30c32f3519d8868;p=mesa.git Implement ir_if (for if-statments) and conversion from AST 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 --- diff --git a/ast.h b/ast.h index a158910421d..53b0e4a2b41 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 7b1db0c4818..0a505bf4146 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 328cd4e4ff5..83e4f95b0cc 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 aeff280cdd9..e6b24d2d5bc 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 8fd684eb92a..76d812e19c1 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 76981f7afc1..521b1c3d805 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; /*@}*/ };