summaryrefslogtreecommitdiff
path: root/src/mesa/program
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-08-26 15:49:33 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-09-03 11:55:21 -0700
commit0f4f8c73644a9cc436500d605413207c44cfb4ee (patch)
tree73cf01cc929bb23102931f55045401a3909444f1 /src/mesa/program
parent53acbd87d712555f9e7a1c304843be7b39641413 (diff)
ir_to_mesa: Handle loops with loop controls set
The downside of our talloc usage is that we can't really make static (i.e., not created with new) instances of our IR types. This leads to a lot of unnecessary dynamic allocation in this patch.
Diffstat (limited to 'src/mesa/program')
-rw-r--r--src/mesa/program/ir_to_mesa.cpp48
1 files changed, 44 insertions, 4 deletions
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index f0e14b8ece..839d6f0467 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -882,13 +882,53 @@ ir_to_mesa_visitor::visit(ir_variable *ir)
void
ir_to_mesa_visitor::visit(ir_loop *ir)
{
- assert(!ir->from);
- assert(!ir->to);
- assert(!ir->increment);
- assert(!ir->counter);
+ ir_dereference_variable *counter = NULL;
+
+ if (ir->counter != NULL)
+ counter = new(ir) ir_dereference_variable(ir->counter);
+
+ if (ir->from != NULL) {
+ assert(ir->counter != NULL);
+
+ ir_assignment *a = new(ir) ir_assignment(counter, ir->from, NULL);
+
+ a->accept(this);
+ delete a;
+ }
ir_to_mesa_emit_op0(NULL, OPCODE_BGNLOOP);
+
+ if (ir->to) {
+ ir_expression *e =
+ new(ir) ir_expression(ir->cmp, glsl_type::bool_type,
+ counter, ir->to);
+ ir_if *if_stmt = new(ir) ir_if(e);
+
+ ir_loop_jump *brk = new(ir) ir_loop_jump(ir_loop_jump::jump_break);
+
+ if_stmt->then_instructions.push_tail(brk);
+
+ if_stmt->accept(this);
+
+ delete if_stmt;
+ delete e;
+ delete brk;
+ }
+
visit_exec_list(&ir->body_instructions, this);
+
+ if (ir->increment) {
+ ir_expression *e =
+ new(ir) ir_expression(ir_binop_add, counter->type,
+ counter, ir->increment);
+
+ ir_assignment *a = new(ir) ir_assignment(counter, e, NULL);
+
+ a->accept(this);
+ delete a;
+ delete e;
+ }
+
ir_to_mesa_emit_op0(NULL, OPCODE_ENDLOOP);
}