summaryrefslogtreecommitdiffstats
path: root/src/mesa/program/ir_to_mesa.cpp
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2010-08-26 15:49:33 -0700
committerIan Romanick <[email protected]>2010-09-03 11:55:21 -0700
commit0f4f8c73644a9cc436500d605413207c44cfb4ee (patch)
tree73cf01cc929bb23102931f55045401a3909444f1 /src/mesa/program/ir_to_mesa.cpp
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/ir_to_mesa.cpp')
-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 f0e14b8ece3..839d6f04673 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);
}