diff options
author | Eric Anholt <[email protected]> | 2010-05-07 12:59:08 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-06-24 15:05:20 -0700 |
commit | 64fcbbca9ca8191b5131304af2026d0ed914b765 (patch) | |
tree | a66a8b1ef9f5842eeb17aa7d5ceb9a84790988a5 | |
parent | 0c005bd773784ee5feb2ee3d7d00c2c4335eafb4 (diff) |
ir_to_mesa: Add support for loops.
Fixes CorrectParse1 and the glsl2 loop tests that don't use arrays.
-rw-r--r-- | ir_to_mesa.cpp | 87 |
1 files changed, 70 insertions, 17 deletions
diff --git a/ir_to_mesa.cpp b/ir_to_mesa.cpp index f45421057b2..2be5bf1ef05 100644 --- a/ir_to_mesa.cpp +++ b/ir_to_mesa.cpp @@ -297,18 +297,37 @@ ir_to_mesa_visitor::visit(ir_variable *ir) void ir_to_mesa_visitor::visit(ir_loop *ir) { - (void)ir; + assert(!ir->from); + assert(!ir->to); + assert(!ir->increment); + assert(!ir->counter); - printf("Can't support loops, should be flattened before here\n"); - exit(1); + ir_to_mesa_emit_op1_full(this, NULL, + OPCODE_BGNLOOP, ir_to_mesa_undef_dst, + ir_to_mesa_undef); + + visit_exec_list(&ir->body_instructions, this); + + ir_to_mesa_emit_op1_full(this, NULL, + OPCODE_ENDLOOP, ir_to_mesa_undef_dst, + ir_to_mesa_undef); } void ir_to_mesa_visitor::visit(ir_loop_jump *ir) { - (void) ir; - printf("Can't support loops, should be flattened before here\n"); - exit(1); + switch (ir->mode) { + case ir_loop_jump::jump_break: + ir_to_mesa_emit_op1_full(this, NULL, + OPCODE_BRK, ir_to_mesa_undef_dst, + ir_to_mesa_undef); + break; + case ir_loop_jump::jump_continue: + ir_to_mesa_emit_op1_full(this, NULL, + OPCODE_CONT, ir_to_mesa_undef_dst, + ir_to_mesa_undef); + break; + } } @@ -805,32 +824,66 @@ static void set_branchtargets(struct prog_instruction *mesa_instructions, int num_instructions) { - int if_count = 0; - struct prog_instruction **if_stack; - int if_stack_pos = 0; - int i; + int if_count = 0, loop_count; + int *if_stack, *loop_stack; + int if_stack_pos = 0, loop_stack_pos = 0; + int i, j; for (i = 0; i < num_instructions; i++) { - if (mesa_instructions[i].Opcode == OPCODE_IF) + switch (mesa_instructions[i].Opcode) { + case OPCODE_IF: if_count++; + break; + case OPCODE_BGNLOOP: + loop_count++; + break; + case OPCODE_BRK: + case OPCODE_CONT: + mesa_instructions[i].BranchTarget = -1; + break; + default: + break; + } } - if_stack = (struct prog_instruction **)calloc(if_count, sizeof(*if_stack)); + if_stack = (int *)calloc(if_count, sizeof(*if_stack)); + loop_stack = (int *)calloc(loop_count, sizeof(*loop_stack)); for (i = 0; i < num_instructions; i++) { switch (mesa_instructions[i].Opcode) { case OPCODE_IF: - if_stack[if_stack_pos] = mesa_instructions + i; + if_stack[if_stack_pos] = i; if_stack_pos++; break; case OPCODE_ELSE: - if_stack[if_stack_pos - 1]->BranchTarget = i; - if_stack[if_stack_pos - 1] = mesa_instructions + i; + mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i; + if_stack[if_stack_pos - 1] = i; break; case OPCODE_ENDIF: - if_stack[if_stack_pos - 1]->BranchTarget = i; + mesa_instructions[if_stack[if_stack_pos - 1]].BranchTarget = i; if_stack_pos--; break; + case OPCODE_BGNLOOP: + loop_stack[loop_stack_pos] = i; + loop_stack_pos++; + break; + case OPCODE_ENDLOOP: + loop_stack_pos--; + /* Rewrite any breaks/conts at this nesting level (haven't + * already had a BranchTarget assigned) to point to the end + * of the loop. + */ + for (j = loop_stack[loop_stack_pos]; j < i; j++) { + if (mesa_instructions[j].Opcode == OPCODE_BRK || + mesa_instructions[j].Opcode == OPCODE_CONT) { + if (mesa_instructions[j].BranchTarget == -1) { + mesa_instructions[j].BranchTarget = i; + } + } + } + /* The loop ends point at each other. */ + mesa_instructions[i].BranchTarget = loop_stack[loop_stack_pos]; + mesa_instructions[loop_stack[loop_stack_pos]].BranchTarget = i; default: break; } @@ -851,7 +904,7 @@ print_program(struct prog_instruction *mesa_instructions, struct prog_instruction *mesa_inst = mesa_instructions + i; ir_instruction *ir = mesa_instruction_annotation[i]; - if (last_ir != ir) { + if (last_ir != ir && ir) { ir_print_visitor print; ir->accept(&print); printf("\n"); |