summaryrefslogtreecommitdiffstats
path: root/src/mesa/shader/slang/slang_codegen.c
diff options
context:
space:
mode:
authorBrian <[email protected]>2007-02-05 15:00:07 -0700
committerBrian <[email protected]>2007-02-05 15:00:07 -0700
commitcf92c727979e434d148b23d20f2e4e0f4bc4de61 (patch)
tree4f4142ad5919f7684216ae580abb627878d958b0 /src/mesa/shader/slang/slang_codegen.c
parent5db088d70fbd14620c2fc7840096a05993f8e2b9 (diff)
Initial implementation of high-level flow-control instructions.
IF/ELSE/ENDIF and BEGIN_LOOP/END_LOOP/BREAK instructions seem to work. Disabled by default though until better tested. Implemented IR_NOT, but needs optimization.
Diffstat (limited to 'src/mesa/shader/slang/slang_codegen.c')
-rw-r--r--src/mesa/shader/slang/slang_codegen.c88
1 files changed, 82 insertions, 6 deletions
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 72f58a9ebd1..2dd9ccc6fdc 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -47,6 +47,8 @@
#include "slang_print.h"
+static GLboolean UseHighLevelInstructions = GL_TRUE;
+
static slang_ir_node *
_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
@@ -506,6 +508,7 @@ new_node(slang_ir_opcode op, slang_ir_node *left, slang_ir_node *right)
n->Children[0] = left;
n->Children[1] = right;
n->Writemask = WRITEMASK_XYZW;
+ n->InstLocation = -1;
}
return n;
}
@@ -567,6 +570,26 @@ new_jump(slang_atom target)
}
+static slang_ir_node *
+new_begin_loop(void)
+{
+ slang_ir_node *n = new_node(IR_BEGIN_LOOP, NULL, NULL);
+ return n;
+}
+
+
+static slang_ir_node *
+new_end_loop(slang_ir_node *beginNode)
+{
+ slang_ir_node *n = new_node(IR_END_LOOP, NULL, NULL);
+ assert(beginNode);
+ if (n) {
+ n->BranchNode = beginNode;
+ }
+ return n;
+}
+
+
/**
* New IR_VAR node - a reference to a previously declared variable.
*/
@@ -1304,7 +1327,7 @@ _slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,
/**
- * Generate IR tree for a while-loop.
+ * Generate IR tree for a while-loop. Use BRA-nch instruction.
*/
static slang_ir_node *
_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
@@ -1313,7 +1336,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
* label "__startWhile"
* eval expr (child[0]), updating condcodes
* branch if false to "__endWhile"
- * code body
+ * body code
* jump "__startWhile"
* label "__endWhile"
*/
@@ -1354,6 +1377,51 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
/**
+ * Generate IR tree for a while-loop using high-level BGNLOOP/ENDLOOP,
+ * IF/ENDIF instructions.
+ */
+static slang_ir_node *
+_slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
+{
+ /*
+ * BGNLOOP
+ * eval expr (child[0]), updating condcodes
+ * IF !expr THEN
+ * BRK
+ * ENDIF
+ * body code
+ * ENDLOOP
+ */
+ slang_ir_node *beginLoop, *endLoop, *ifThen, *endif;
+ slang_ir_node *brk, *cond, *body, *tree;
+
+ beginLoop = new_begin_loop();
+
+ cond = _slang_gen_operation(A, &oper->children[0]);
+ cond = new_node(IR_NOT, cond, NULL);
+ cond = _slang_gen_cond(cond);
+
+ ifThen = new_node(IR_IF, cond, NULL);
+ tree = new_seq(beginLoop, ifThen);
+
+ brk = new_node(IR_BREAK, NULL, NULL);
+ tree = new_seq(tree, brk);
+
+ endif = new_node(IR_ENDIF, NULL, NULL);
+ tree = new_seq(tree, endif);
+
+ body = _slang_gen_operation(A, &oper->children[1]);
+ if (body)
+ tree = new_seq(tree, body);
+
+ endLoop = new_end_loop(beginLoop);
+ tree = new_seq(tree, endLoop);
+
+ return tree;
+}
+
+
+/**
* Generate IR tree for a do-while-loop.
*/
static slang_ir_node *
@@ -1517,7 +1585,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
* IF/ELSE/ENDIF instructions
*/
static slang_ir_node *
-_slang_gen_if2(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_hl_if(slang_assemble_ctx * A, const slang_operation *oper)
{
/*
* eval expr (child[0]), updating condcodes
@@ -1529,6 +1597,10 @@ _slang_gen_if2(slang_assemble_ctx * A, const slang_operation *oper)
* "false" code block
* label "__endif"
*/
+ /* XXX special cases to check for:
+ * if body of conditiona is just a "break", emit a conditional break
+ * instruction.
+ */
const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
slang_ir_node *ifNode, *cond, *trueBody, *elseNode, *falseBody, *endifNode;
slang_ir_node *tree;
@@ -2261,7 +2333,10 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
return _slang_gen_operation(A, &oper->children[0]);
break;
case slang_oper_while:
- return _slang_gen_while(A, oper);
+ if (UseHighLevelInstructions)
+ return _slang_gen_hl_while(A, oper);
+ else
+ return _slang_gen_while(A, oper);
case slang_oper_do:
return _slang_gen_do(A, oper);
case slang_oper_for:
@@ -2427,8 +2502,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
case slang_oper_identifier:
return _slang_gen_variable(A, oper);
case slang_oper_if:
- if (A->program->Target == GL_FRAGMENT_PROGRAM_ARB) {
- return _slang_gen_if(A, oper);
+ if (A->program->Target == GL_FRAGMENT_PROGRAM_ARB
+ && UseHighLevelInstructions) {
+ return _slang_gen_hl_if(A, oper);
}
else {
/* XXX update tnl executor */