summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang/slang_codegen.c
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-02-05 18:01:02 -0700
committerBrian <brian@yutani.localnet.net>2007-02-05 18:01:02 -0700
commit2755c798f3cb89fcd4ece16cd740af1cd86a6b99 (patch)
tree423205b0b37cf79f08f4b2b0a6d2a845e6f1dbc2 /src/mesa/shader/slang/slang_codegen.c
parent86080796471df6a9e126fd536b21c3b10cb5310c (diff)
BRK instruction's BranchTarget field now used for efficiently breaking out of loops.
BRK's BranchTarget field actually points to the top of the loop, not the bottom, since we don't know the later's location yet. In the interpreter, basically do an indirect jump to update the PC.
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c90
1 files changed, 87 insertions, 3 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 7a1881c68e..a5f033d912 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -590,6 +590,18 @@ new_end_loop(slang_ir_node *beginNode)
}
+static slang_ir_node *
+new_break(slang_ir_node *beginNode)
+{
+ slang_ir_node *n = new_node(IR_BREAK, NULL, NULL);
+ assert(beginNode);
+ if (n) {
+ n->BranchNode = beginNode;
+ }
+ return n;
+}
+
+
/**
* Child[0] is the condition.
* XXX we might re-design IR_IF so Children[1] is the "then" body and
@@ -1430,7 +1442,7 @@ _slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
* IF !expr THEN
* BRK
* ENDIF
- * body code
+ * body code (child[1])
* ENDLOOP
*/
slang_ir_node *beginLoop, *endLoop, *ifThen, *endif;
@@ -1445,7 +1457,7 @@ _slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
ifThen = new_if(cond);
tree = new_seq(beginLoop, ifThen);
- brk = new_node(IR_BREAK, NULL, NULL);
+ brk = new_break(beginLoop);
tree = new_seq(tree, brk);
endif = new_endif(ifThen);
@@ -1572,6 +1584,73 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
/**
+ * Generate IR tree for a for-loop, using high-level BGNLOOP/ENDLOOP and
+ * IF/ENDIF instructions.
+ *
+ * XXX note done yet!
+ */
+static slang_ir_node *
+_slang_gen_hl_for(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ /*
+ * init code (child[0])
+ * BGNLOOP
+ * eval expr (child[1]), updating condcodes
+ * IF !expr THEN
+ * BRK
+ * ENDIF
+ * code body (child[3])
+ * label "__continueFor" // jump here for "continue"
+ * incr code (child[2])
+ * ENDLOOP
+ */
+ slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startFor");
+ slang_atom contAtom = slang_atom_pool_gen(A->atoms, "__continueFor");
+ slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endFor");
+ slang_ir_node *init, *startLab, *cond, *bra, *body, *contLab;
+ slang_ir_node *incr, *jump, *endLab, *tree;
+ slang_atom prevLoopBreak = A->CurLoopBreak;
+ slang_atom prevLoopCont = A->CurLoopCont;
+
+ /* Push this loop */
+ A->CurLoopBreak = endAtom;
+ A->CurLoopCont = contAtom;
+
+ init = _slang_gen_operation(A, &oper->children[0]);
+ startLab = new_label(startAtom);
+ tree = new_seq(init, startLab);
+
+ cond = _slang_gen_operation(A, &oper->children[1]);
+ cond = _slang_gen_cond(cond);
+ tree = new_seq(tree, cond);
+
+ bra = new_cjump(endAtom, 0);
+ tree = new_seq(tree, bra);
+
+ body = _slang_gen_operation(A, &oper->children[3]);
+ tree = new_seq(tree, body);
+
+ contLab = new_label(contAtom);
+ tree = new_seq(tree, contLab);
+
+ incr = _slang_gen_operation(A, &oper->children[2]);
+ tree = new_seq(tree, incr);
+
+ jump = new_jump(startAtom);
+ tree = new_seq(tree, jump);
+
+ endLab = new_label(endAtom);
+ tree = new_seq(tree, endLab);
+
+ /* Pop this loop */
+ A->CurLoopBreak = prevLoopBreak;
+ A->CurLoopCont = prevLoopCont;
+
+ return tree;
+}
+
+
+/**
* Generate IR tree for an if/then/else conditional using BRAnch instructions.
*/
static slang_ir_node *
@@ -2378,16 +2457,21 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
case slang_oper_do:
return _slang_gen_do(A, oper);
case slang_oper_for:
- return _slang_gen_for(A, oper);
+ if (UseHighLevelInstructions)
+ return _slang_gen_hl_for(A, oper);
+ else
+ return _slang_gen_for(A, oper);
case slang_oper_break:
if (!A->CurLoopBreak) {
RETURN_ERROR("'break' not in loop", 0);
}
+ /* XXX emit IR_BREAK instruction */
return new_jump(A->CurLoopBreak);
case slang_oper_continue:
if (!A->CurLoopCont) {
RETURN_ERROR("'continue' not in loop", 0);
}
+ /* XXX emit IR_CONT instruction */
return new_jump(A->CurLoopCont);
case slang_oper_discard:
return new_node(IR_KILL, NULL, NULL);