summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/slang/slang_codegen.c
diff options
context:
space:
mode:
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 7a1881c68ee..a5f033d9123 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);