summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-02-05 17:18:10 -0700
committerBrian <brian@yutani.localnet.net>2007-02-05 17:18:10 -0700
commit86080796471df6a9e126fd536b21c3b10cb5310c (patch)
tree26d7c96f3aa66061aacf5c9ca68f1a073b685f93
parentd9731b26e759671d63e357eee2c921e90448ada2 (diff)
Use IR node's BranchNode field for IF/ELSE/ENDIF instructions.
This allows us to back-patch the IF/ELSE instruction's BranchTarget field to point to the location of the ELSE/ENDIF instructions. No longer have to search for ELSE/ENDIF in the interpreter. Also makes it trivial to translate IF/ELSE instructions into conditional/unconditional BRA instructions.
-rw-r--r--src/mesa/shader/prog_print.c7
-rw-r--r--src/mesa/shader/slang/slang_codegen.c64
-rw-r--r--src/mesa/shader/slang/slang_emit.c12
-rw-r--r--src/mesa/swrast/s_fragprog.c57
4 files changed, 73 insertions, 67 deletions
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 208c998661..aea11da0db 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -319,13 +319,14 @@ _mesa_print_instruction(const struct prog_instruction *inst, GLint indent)
print_comment(inst);
break;
case OPCODE_IF:
- _mesa_printf("IF (%s%s)",
+ _mesa_printf("IF (%s%s) (if false, goto %d)",
condcode_string(inst->DstReg.CondMask),
- swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+ swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
+ inst->BranchTarget);
print_comment(inst);
return indent + 3;
case OPCODE_ELSE:
- _mesa_printf("ELSE\n");
+ _mesa_printf("ELSE (goto %d)\n", inst->BranchTarget);
return indent + 3;
case OPCODE_ENDIF:
_mesa_printf("ENDIF\n");
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index c70f73f15a..7a1881c68e 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -591,6 +591,47 @@ new_end_loop(slang_ir_node *beginNode)
/**
+ * Child[0] is the condition.
+ * XXX we might re-design IR_IF so Children[1] is the "then" body and
+ * Children[0] is the "else" body.
+ */
+static slang_ir_node *
+new_if(slang_ir_node *cond)
+{
+ slang_ir_node *n = new_node(IR_IF, NULL, NULL);
+ assert(cond);
+ if (n) {
+ n->Children[0] = cond;
+ }
+ return n;
+}
+
+
+static slang_ir_node *
+new_else(slang_ir_node *ifNode)
+{
+ slang_ir_node *n = new_node(IR_ELSE, NULL, NULL);
+ assert(ifNode);
+ if (n) {
+ n->BranchNode = ifNode;
+ }
+ return n;
+}
+
+
+static slang_ir_node *
+new_endif(slang_ir_node *elseOrIfNode)
+{
+ slang_ir_node *n = new_node(IR_ENDIF, NULL, NULL);
+ assert(elseOrIfNode);
+ if (n) {
+ n->BranchNode = elseOrIfNode;
+ }
+ return n;
+}
+
+
+/**
* New IR_VAR node - a reference to a previously declared variable.
*/
static slang_ir_node *
@@ -1401,13 +1442,13 @@ _slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
cond = new_node(IR_NOT, cond, NULL);
cond = _slang_gen_cond(cond);
- ifThen = new_node(IR_IF, cond, NULL);
+ ifThen = new_if(cond);
tree = new_seq(beginLoop, ifThen);
brk = new_node(IR_BREAK, NULL, NULL);
tree = new_seq(tree, brk);
- endif = new_node(IR_ENDIF, NULL, NULL);
+ endif = new_endif(ifThen);
tree = new_seq(tree, endif);
body = _slang_gen_operation(A, &oper->children[1]);
@@ -1589,13 +1630,11 @@ _slang_gen_hl_if(slang_assemble_ctx * A, const slang_operation *oper)
{
/*
* eval expr (child[0]), updating condcodes
- * branch if false to _else or _endif
- * "true" code block
- * if haveElseClause clause:
- * jump "__endif"
- * label "__else"
- * "false" code block
- * label "__endif"
+ * IF expr THEN
+ * if-body code
+ * ELSE
+ * else-body code
+ * ENDIF
*/
/* XXX special cases to check for:
* if body of conditiona is just a "break", emit a conditional break
@@ -1608,21 +1647,20 @@ _slang_gen_hl_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);*/
- ifNode = new_node(IR_IF, cond, NULL);
+ ifNode = new_if(cond);
trueBody = _slang_gen_operation(A, &oper->children[1]);
tree = new_seq(ifNode, trueBody);
if (haveElseClause) {
- /* else clause */
- elseNode = new_node(IR_ELSE, NULL, NULL);
+ elseNode = new_else(ifNode);
tree = new_seq(tree, elseNode);
falseBody = _slang_gen_operation(A, &oper->children[2]);
tree = new_seq(tree, falseBody);
}
- endifNode = new_node(IR_ENDIF, NULL, NULL);
+ endifNode = new_endif(haveElseClause ? elseNode : ifNode);
tree = new_seq(tree, endifNode);
return tree;
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 311eea1e6a..b890a6d93c 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -1036,6 +1036,7 @@ emit_not(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
free_temp_storage(vt, n->Children[0]);
+ inst->Comment = _mesa_strdup("NOT");
return inst;
}
@@ -1259,18 +1260,29 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
inst = new_instruction(prog, OPCODE_IF);
inst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
inst->DstReg.CondSwizzle = SWIZZLE_X;
+ n->InstLocation = prog->NumInstructions - 1;
return inst;
}
case IR_ELSE:
{
struct prog_instruction *inst;
+ n->InstLocation = prog->NumInstructions;
inst = new_instruction(prog, OPCODE_ELSE);
+ /* point IF's BranchTarget just after this instruction */
+ assert(n->BranchNode);
+ assert(n->BranchNode->InstLocation >= 0);
+ prog->Instructions[n->BranchNode->InstLocation].BranchTarget = prog->NumInstructions;
return inst;
}
case IR_ENDIF:
{
struct prog_instruction *inst;
+ n->InstLocation = prog->NumInstructions;
inst = new_instruction(prog, OPCODE_ENDIF);
+ /* point ELSE's BranchTarget to just after this inst */
+ assert(n->BranchNode);
+ assert(n->BranchNode->InstLocation >= 0);
+ prog->Instructions[n->BranchNode->InstLocation].BranchTarget = prog->NumInstructions;
return inst;
}
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index 287dd9b1db..fbd25c0fbf 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -897,62 +897,17 @@ execute_program( GLcontext *ctx,
/* do if-clause (just continue execution) */
}
else {
- /* search for else-clause or endif */
- /* XXX could encode location of the else/endif statement
- * in the IF instruction to avoid searching...
- */
- GLint ifDepth = 1;
- do {
- pc++;
- inst = program->Base.Instructions + pc;
- if (inst->Opcode == OPCODE_END) {
- /* mal-formed program! */
- _mesa_problem(ctx, "END found before ELSE/ENDIF");
- return GL_FALSE;
- }
- else if (inst->Opcode == OPCODE_IF) {
- /* nested if */
- ifDepth++;
- }
- else if (inst->Opcode == OPCODE_ELSE) {
- if (ifDepth == 1) {
- /* ok, continue normal execution */
- break;
- }
- }
- else if (inst->Opcode == OPCODE_ENDIF) {
- ifDepth--;
- if (ifDepth == 0) {
- /* ok, continue normal execution */
- break;
- }
- }
- assert(ifDepth >= 0);
- } while (pc < maxInst);
+ /* go to the instruction after ELSE or ENDIF */
+ assert(inst->BranchTarget >= 0);
+ pc = inst->BranchTarget - 1;
}
}
break;
case OPCODE_ELSE:
{
- /* find/goto ENDIF */
- GLint ifDepth = 1;
- do {
- pc++;
- inst = program->Base.Instructions + pc;
- if (inst->Opcode == OPCODE_END) {
- /* mal-formed program! */
- abort();
- }
- else if (inst->Opcode == OPCODE_IF) {
- ifDepth++;
- }
- else if (inst->Opcode == OPCODE_ENDIF) {
- ifDepth--;
- if (ifDepth == 0)
- break;
- }
- assert(ifDepth >= 0);
- } while (pc < maxInst);
+ /* goto ENDIF */
+ assert(inst->BranchTarget >= 0);
+ pc = inst->BranchTarget - 1;
}
break;
case OPCODE_ENDIF: