summaryrefslogtreecommitdiff
path: root/src/mesa/shader
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-01-19 13:13:15 -0700
committerBrian <brian@yutani.localnet.net>2007-01-19 13:13:15 -0700
commit3cec66512de9c424088ff4fd9332bcceec8ee3c6 (patch)
treeded3abcdef36414cf4c68514e3ca2c6d12628f66 /src/mesa/shader
parenteff9690351c07940a976fade4302b480e9731917 (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.
Diffstat (limited to 'src/mesa/shader')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c66
-rw-r--r--src/mesa/shader/slang/slang_emit.c26
-rw-r--r--src/mesa/shader/slang/slang_ir.h3
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 76dcca576d..60bf57035f 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 c660f2ceac..9dda28d842 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 a337d61712..4072c70f90 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,