diff options
author | Brian <[email protected]> | 2007-01-19 13:13:15 -0700 |
---|---|---|
committer | Brian <[email protected]> | 2007-01-19 13:13:15 -0700 |
commit | 3cec66512de9c424088ff4fd9332bcceec8ee3c6 (patch) | |
tree | ded3abcdef36414cf4c68514e3ca2c6d12628f66 | |
parent | eff9690351c07940a976fade4302b480e9731917 (diff) |
Implement do/while loops. Replace IR_CJUMP with IR_CJUMP0 and IR_CJUMP1 so
we can either jump on zero, or non-zero predicate.
-rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 66 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 26 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_ir.h | 3 |
3 files changed, 79 insertions, 16 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 76dcca576d2..60bf57035f0 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -562,18 +562,22 @@ new_float_literal(float x, float y, float z, float w) } /** + * Conditional jump. + * \param zeroOrOne indicates if the jump is to be taken on zero, or non-zero + * condition code state. * XXX maybe pass an IR node as second param to indicate the jump target??? */ static slang_ir_node * -new_cjump(slang_atom target) +new_cjump(slang_atom target, GLuint zeroOrOne) { - slang_ir_node *n = new_node(IR_CJUMP, NULL, NULL); + slang_ir_node *n = new_node(zeroOrOne ? IR_CJUMP1 : IR_CJUMP0, NULL, NULL); if (n) n->Target = (char *) target; return n; } /** + * Unconditional jump. * XXX maybe pass an IR node as second param to indicate the jump target??? */ static slang_ir_node * @@ -1386,7 +1390,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper) cond = _slang_gen_cond(cond); tree = new_seq(startLab, cond); - bra = new_cjump(endAtom); + bra = new_cjump(endAtom, 0); tree = new_seq(tree, bra); body = _slang_gen_operation(A, &oper->children[1]); @@ -1407,6 +1411,52 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper) /** + * Generate IR tree for a do-while-loop. + */ +static slang_ir_node * +_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper) +{ + /* + * label "__startDo" + * code body + * eval expr (child[0]), updating condcodes + * branch if true to "__startDo" + * label "__endDo" + */ + slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startDo"); + slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endDo"); + slang_ir_node *startLab, *cond, *bra, *body, *endLab, *tree; + slang_atom prevLoopBreak = A->CurLoopBreak; + slang_atom prevLoopCont = A->CurLoopCont; + + /* Push this loop */ + A->CurLoopBreak = endAtom; + A->CurLoopCont = startAtom; + + startLab = new_label(startAtom); + + body = _slang_gen_operation(A, &oper->children[0]); + tree = new_seq(startLab, body); + + cond = _slang_gen_operation(A, &oper->children[1]); + cond = _slang_gen_cond(cond); + tree = new_seq(tree, cond); + + bra = new_cjump(startAtom, 1); + tree = new_seq(tree, bra); + + endLab = new_label(endAtom); + tree = new_seq(tree, endLab); + + /* Pop this loop */ + A->CurLoopBreak = prevLoopBreak; + A->CurLoopCont = prevLoopCont; + + return tree; +} + + +/** * Generate IR tree for a for-loop. */ static slang_ir_node * @@ -1443,7 +1493,7 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper) cond = _slang_gen_cond(cond); tree = new_seq(tree, cond); - bra = new_cjump(endAtom); + bra = new_cjump(endAtom, 0); tree = new_seq(tree, bra); body = _slang_gen_operation(A, &oper->children[3]); @@ -1493,7 +1543,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper) cond = _slang_gen_operation(A, &oper->children[0]); cond = _slang_gen_cond(cond); /*assert(cond->Store);*/ - bra = new_cjump(haveElseClause ? elseAtom : endifAtom); + bra = new_cjump(haveElseClause ? elseAtom : endifAtom, 0); tree = new_seq(cond, bra); trueBody = _slang_gen_operation(A, &oper->children[1]); @@ -1593,8 +1643,8 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) cond = _slang_gen_cond(cond); tree = new_seq(tmpDecl, cond); - /* jump if true to "alt" label */ - cjump = new_cjump(altAtom); + /* jump if false to "alt" label */ + cjump = new_cjump(altAtom, 0); tree = new_seq(tree, cjump); /* evaluate child 2 (y) and assign to tmp */ @@ -2042,6 +2092,8 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) break; case slang_oper_while: return _slang_gen_while(A, oper); + case slang_oper_do: + return _slang_gen_do(A, oper); case slang_oper_for: return _slang_gen_for(A, oper); case slang_oper_break: diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index c660f2ceac6..9dda28d842e 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -89,7 +89,8 @@ static slang_ir_info IrInfo[] = { { IR_SCOPE, "IR_SCOPE", 0, 0, 0 }, { IR_LABEL, "IR_LABEL", 0, 0, 0 }, { IR_JUMP, "IR_JUMP", 0, 0, 0 }, - { IR_CJUMP, "IR_CJUMP", 0, 0, 0 }, + { IR_CJUMP0, "IR_CJUMP0", 0, 0, 0 }, + { IR_CJUMP1, "IR_CJUMP1", 0, 0, 0 }, { IR_KILL, "IR_KILL", 0, 0, 0 }, { IR_COND, "IR_COND", 0, 0, 0 }, { IR_CALL, "IR_CALL", 0, 0, 0 }, @@ -262,8 +263,12 @@ slang_print_ir(const slang_ir_node *n, int indent) case IR_JUMP: printf("JUMP %s\n", n->Target); break; - case IR_CJUMP: - printf("CJUMP %s\n", n->Target); + case IR_CJUMP0: + printf("CJUMP0 %s\n", n->Target); + slang_print_ir(n->Children[0], indent+3); + break; + case IR_CJUMP1: + printf("CJUMP1 %s\n", n->Target); slang_print_ir(n->Children[0], indent+3); break; case IR_VAR: @@ -515,11 +520,14 @@ emit_label(const char *target, struct gl_program *prog) static struct prog_instruction * -emit_cjump(const char *target, struct gl_program *prog) +emit_cjump(const char *target, struct gl_program *prog, GLuint zeroOrOne) { struct prog_instruction *inst; inst = new_instruction(prog, OPCODE_BRA); - inst->DstReg.CondMask = COND_EQ; /* branch if equal to zero */ + if (zeroOrOne) + inst->DstReg.CondMask = COND_NE; /* branch if non-zero */ + else + inst->DstReg.CondMask = COND_EQ; /* branch if equal to zero */ inst->DstReg.CondSwizzle = SWIZZLE_X; inst->Comment = _mesa_strdup(target); return inst; @@ -666,7 +674,7 @@ emit_cond(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) { /* Conditional expression (in if/while/for stmts). * Need to update condition code register. - * Next instruction is typically an IR_CJUMP. + * Next instruction is typically an IR_CJUMP0/1. */ /* last child expr instruction: */ struct prog_instruction *inst = emit(vt, n->Children[0], prog); @@ -842,8 +850,10 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) return emit_label(n->Target, prog); case IR_JUMP: return emit_jump(n->Target, prog); - case IR_CJUMP: - return emit_cjump(n->Target, prog); + case IR_CJUMP0: + return emit_cjump(n->Target, prog, 0); + case IR_CJUMP1: + return emit_cjump(n->Target, prog, 1); case IR_KILL: return emit_kill(prog); diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index a337d61712b..4072c70f902 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -48,7 +48,8 @@ typedef enum IR_SCOPE, /* new variable scope (one child) */ IR_LABEL, /* target of a jump or cjump */ IR_JUMP, /* unconditional jump */ - IR_CJUMP, /* conditional jump */ + IR_CJUMP0, /* conditional jump if zero */ + IR_CJUMP1, /* conditional jump if one (or non-zero) */ IR_COND, /* conditional expression */ IR_CALL, /* call subroutine */ IR_MOVE, |