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");
}
+/**
+ * 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.
*/
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]);
{
/*
* 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
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;
free_temp_storage(vt, n->Children[0]);
+ inst->Comment = _mesa_strdup("NOT");
return inst;
}
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;
}
/* 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: