diff options
author | Eric Anholt <[email protected]> | 2010-05-07 11:31:47 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2010-06-24 15:05:20 -0700 |
commit | c5ca73e72c27b2e5d7fcf4662b9921ddb3a9627b (patch) | |
tree | c5b9f049c56ba710f7f7b925bccb354b85765b45 | |
parent | 38315079571512dc5b502d9522d7a8c3eaf2cc8f (diff) |
ir_to_mesa: Add support for ir_if.
-rw-r--r-- | ir_to_mesa.cpp | 138 | ||||
-rw-r--r-- | ir_to_mesa.h | 9 | ||||
-rw-r--r-- | mesa_codegen.brg | 8 |
3 files changed, 125 insertions, 30 deletions
diff --git a/ir_to_mesa.cpp b/ir_to_mesa.cpp index 465a8e19164..487e24986f9 100644 --- a/ir_to_mesa.cpp +++ b/ir_to_mesa.cpp @@ -54,8 +54,13 @@ ir_to_mesa_src_reg ir_to_mesa_undef = { PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP }; +ir_to_mesa_dst_reg ir_to_mesa_undef_dst = { + PROGRAM_UNDEFINED, 0, SWIZZLE_NOOP +}; + ir_to_mesa_instruction * -ir_to_mesa_emit_op3(struct mbtree *tree, enum prog_opcode op, +ir_to_mesa_emit_op3(ir_to_mesa_visitor *v, ir_instruction *ir, + enum prog_opcode op, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0, ir_to_mesa_src_reg src1, @@ -68,45 +73,48 @@ ir_to_mesa_emit_op3(struct mbtree *tree, enum prog_opcode op, inst->src_reg[0] = src0; inst->src_reg[1] = src1; inst->src_reg[2] = src2; - inst->ir = tree->ir; + inst->ir = ir; - tree->v->instructions.push_tail(inst); + v->instructions.push_tail(inst); return inst; } ir_to_mesa_instruction * -ir_to_mesa_emit_op2_full(struct mbtree *tree, enum prog_opcode op, +ir_to_mesa_emit_op2_full(ir_to_mesa_visitor *v, ir_instruction *ir, + enum prog_opcode op, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0, ir_to_mesa_src_reg src1) { - return ir_to_mesa_emit_op3(tree, op, dst, src0, src1, ir_to_mesa_undef); + return ir_to_mesa_emit_op3(v, ir, + op, dst, src0, src1, ir_to_mesa_undef); } ir_to_mesa_instruction * ir_to_mesa_emit_op2(struct mbtree *tree, enum prog_opcode op) { - return ir_to_mesa_emit_op2_full(tree, op, + return ir_to_mesa_emit_op2_full(tree->v, tree->ir, op, tree->dst_reg, tree->left->src_reg, tree->right->src_reg); } ir_to_mesa_instruction * -ir_to_mesa_emit_op1_full(struct mbtree *tree, enum prog_opcode op, +ir_to_mesa_emit_op1_full(ir_to_mesa_visitor *v, ir_instruction *ir, + enum prog_opcode op, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0) { - return ir_to_mesa_emit_op3(tree, op, + return ir_to_mesa_emit_op3(v, ir, op, dst, src0, ir_to_mesa_undef, ir_to_mesa_undef); } ir_to_mesa_instruction * ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op) { - return ir_to_mesa_emit_op1_full(tree, op, + return ir_to_mesa_emit_op1_full(tree->v, tree->ir, op, tree->dst_reg, tree->left->src_reg); } @@ -148,7 +156,7 @@ ir_to_mesa_emit_scalar_op1(struct mbtree *tree, enum prog_opcode op, src.swizzle = MAKE_SWIZZLE4(src_swiz, src_swiz, src_swiz, src_swiz); - inst = ir_to_mesa_emit_op1_full(tree, op, + inst = ir_to_mesa_emit_op1_full(tree->v, tree->ir, op, dst, src); inst->dst_reg.writemask = this_mask; @@ -703,9 +711,29 @@ ir_to_mesa_visitor::visit(ir_return *ir) void ir_to_mesa_visitor::visit(ir_if *ir) { - (void)ir; - printf("Can't support conditionals, should be flattened before here.\n"); - exit(1); + ir_to_mesa_instruction *if_inst, *else_inst = NULL; + + ir->condition->accept(this); + assert(this->result); + + if_inst = ir_to_mesa_emit_op1_full(this, ir->condition, + OPCODE_IF, ir_to_mesa_undef_dst, + this->result->src_reg); + + this->instructions.push_tail(if_inst); + + visit_exec_list(&ir->then_instructions, this); + + if (!ir->else_instructions.is_empty()) { + else_inst = ir_to_mesa_emit_op1_full(this, ir->condition, + OPCODE_ELSE, ir_to_mesa_undef_dst, + ir_to_mesa_undef); + visit_exec_list(&ir->then_instructions, this); + } + + if_inst = ir_to_mesa_emit_op1_full(this, ir->condition, + OPCODE_ENDIF, ir_to_mesa_undef_dst, + ir_to_mesa_undef); } ir_to_mesa_visitor::ir_to_mesa_visitor() @@ -728,12 +756,74 @@ mesa_src_reg_from_ir_src_reg(ir_to_mesa_src_reg reg) return mesa_reg; } +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; + + for (i = 0; i < num_instructions; i++) { + if (mesa_instructions[i].Opcode == OPCODE_IF) + if_count++; + } + + if_stack = (struct prog_instruction **)calloc(if_count, sizeof(*if_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_pos++; + break; + case OPCODE_ELSE: + if_stack[if_stack_pos - 1]->BranchTarget = i; + if_stack[if_stack_pos - 1] = mesa_instructions + i; + break; + case OPCODE_ENDIF: + if_stack[if_stack_pos - 1]->BranchTarget = i; + if_stack_pos--; + break; + default: + break; + } + } + + free(if_stack); +} + +static void +print_program(struct prog_instruction *mesa_instructions, + ir_instruction **mesa_instruction_annotation, + int num_instructions) +{ + ir_instruction *last_ir = NULL; + int i; + + for (i = 0; i < num_instructions; i++) { + struct prog_instruction *mesa_inst = mesa_instructions + i; + ir_instruction *ir = mesa_instruction_annotation[i]; + + if (last_ir != ir) { + ir_print_visitor print; + ir->accept(&print); + printf("\n"); + last_ir = ir; + } + + _mesa_print_instruction(mesa_inst); + } +} + void do_ir_to_mesa(exec_list *instructions) { ir_to_mesa_visitor v; struct prog_instruction *mesa_instructions, *mesa_inst; - ir_instruction *last_ir = NULL; + ir_instruction **mesa_instruction_annotation; + int i; visit_exec_list(instructions, &v); @@ -745,18 +835,15 @@ do_ir_to_mesa(exec_list *instructions) mesa_instructions = (struct prog_instruction *)calloc(num_instructions, sizeof(*mesa_instructions)); + mesa_instruction_annotation = + (ir_instruction **)calloc(num_instructions, + sizeof(*mesa_instruction_annotation)); mesa_inst = mesa_instructions; + i = 0; foreach_iter(exec_list_iterator, iter, v.instructions) { ir_to_mesa_instruction *inst = (ir_to_mesa_instruction *)iter.get(); - if (last_ir != inst->ir) { - ir_print_visitor print; - inst->ir->accept(&print); - printf("\n"); - last_ir = inst->ir; - } - mesa_inst->Opcode = inst->op; mesa_inst->DstReg.File = inst->dst_reg.file; mesa_inst->DstReg.Index = inst->dst_reg.index; @@ -765,9 +852,14 @@ do_ir_to_mesa(exec_list *instructions) mesa_inst->SrcReg[0] = mesa_src_reg_from_ir_src_reg(inst->src_reg[0]); mesa_inst->SrcReg[1] = mesa_src_reg_from_ir_src_reg(inst->src_reg[1]); mesa_inst->SrcReg[2] = mesa_src_reg_from_ir_src_reg(inst->src_reg[2]); - - _mesa_print_instruction(mesa_inst); + mesa_instruction_annotation[i] = inst->ir; mesa_inst++; + i++; } + + set_branchtargets(mesa_instructions, num_instructions); + print_program(mesa_instructions, mesa_instruction_annotation, num_instructions); + + free(mesa_instruction_annotation); } diff --git a/ir_to_mesa.h b/ir_to_mesa.h index ffa27dbd00f..3aa88bcdc40 100644 --- a/ir_to_mesa.h +++ b/ir_to_mesa.h @@ -148,7 +148,8 @@ ir_to_mesa_instruction * ir_to_mesa_emit_op1(struct mbtree *tree, enum prog_opcode op); ir_to_mesa_instruction * -ir_to_mesa_emit_op1_full(struct mbtree *tree, enum prog_opcode op, +ir_to_mesa_emit_op1_full(ir_to_mesa_visitor *v, ir_instruction *ir, + enum prog_opcode op, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0); @@ -156,7 +157,8 @@ ir_to_mesa_instruction * ir_to_mesa_emit_op2(struct mbtree *tree, enum prog_opcode op); ir_to_mesa_instruction * -ir_to_mesa_emit_op2_full(struct mbtree *tree, enum prog_opcode op, +ir_to_mesa_emit_op2_full(ir_to_mesa_visitor *v, ir_instruction *ir, + enum prog_opcode op, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0, ir_to_mesa_src_reg src1); @@ -165,7 +167,8 @@ ir_to_mesa_instruction * ir_to_mesa_emit_simple_op2(struct mbtree *tree, enum prog_opcode op); ir_to_mesa_instruction * -ir_to_mesa_emit_op3(struct mbtree *tree, enum prog_opcode op, +ir_to_mesa_emit_op3(ir_to_mesa_visitor *v, ir_instruction *ir, + enum prog_opcode op, ir_to_mesa_dst_reg dst, ir_to_mesa_src_reg src0, ir_to_mesa_src_reg src1, diff --git a/mesa_codegen.brg b/mesa_codegen.brg index 4e761343ae3..a906542dd53 100644 --- a/mesa_codegen.brg +++ b/mesa_codegen.brg @@ -116,7 +116,7 @@ vec4: reference_vec4 0 # which would clean these up. stmt: assign(vec4, vec4) 1 { - ir_to_mesa_emit_op1_full(tree, OPCODE_MOV, + ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_MOV, tree->left->dst_reg, tree->right->src_reg); } @@ -137,7 +137,7 @@ vec4: swizzle_vec4(vec4) 1 } reg.swizzle = MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]); - ir_to_mesa_emit_op1_full(tree, OPCODE_MOV, + ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_MOV, tree->dst_reg, reg); } @@ -171,7 +171,7 @@ vec4: div_vec4_vec4(vec4, vec4) 1 tree->dst_reg, tree->right->src_reg); - ir_to_mesa_emit_op2_full(tree, OPCODE_MUL, + ir_to_mesa_emit_op2_full(tree->v, tree->ir, OPCODE_MUL, tree->dst_reg, tree->src_reg, tree->left->src_reg); @@ -190,7 +190,7 @@ vec4: sqrt_vec4(vec4) 1 tree->dst_reg, tree->left->src_reg); - ir_to_mesa_emit_op1_full(tree, OPCODE_RCP, + ir_to_mesa_emit_op1_full(tree->v, tree->ir, OPCODE_RCP, tree->dst_reg, tree->src_reg); } |