#include "slang_print.h"
-static GLboolean UseHighLevelInstructions = GL_FALSE;
+static GLboolean UseHighLevelInstructions = GL_TRUE;
static slang_ir_node *
_slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper);
}
-/**
- * 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)
+new_if(slang_ir_node *cond, slang_ir_node *ifPart, slang_ir_node *elsePart)
{
- slang_ir_node *n = new_node(IR_IF, NULL, NULL);
+ slang_ir_node *n = new_node(IR_IF, cond, ifPart);
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;
+ n->Children[2] = elsePart;
}
return n;
}
* body code (child[1])
* ENDLOOP
*/
- slang_ir_node *beginLoop, *endLoop, *ifThen, *endif;
- slang_ir_node *brk, *cond, *body, *tree;
+ slang_ir_node *beginLoop, *endLoop, *ifThen;
+ slang_ir_node *cond, *body, *tree;
beginLoop = new_begin_loop();
cond = new_node(IR_NOT, cond, NULL);
cond = _slang_gen_cond(cond);
- ifThen = new_if(cond);
+ ifThen = new_if(cond,
+ new_break(beginLoop),
+ NULL);
tree = new_seq(beginLoop, ifThen);
- brk = new_break(beginLoop);
- tree = new_seq(tree, brk);
-
- endif = new_endif(ifThen);
- tree = new_seq(tree, endif);
-
body = _slang_gen_operation(A, &oper->children[1]);
if (body)
tree = new_seq(tree, body);
/**
* Generate IR tree for an if/then/else conditional using high-level
- * IF/ELSE/ENDIF instructions
+ * IR_IF instruction.
*/
static slang_ir_node *
_slang_gen_hl_if(slang_assemble_ctx * A, const slang_operation *oper)
* instruction.
*/
const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
- slang_ir_node *ifNode, *cond, *trueBody, *elseNode, *falseBody, *endifNode;
- slang_ir_node *tree;
+ slang_ir_node *ifNode, *cond, *ifBody, *elseBody;
cond = _slang_gen_operation(A, &oper->children[0]);
cond = _slang_gen_cond(cond);
- /*assert(cond->Store);*/
- ifNode = new_if(cond);
-
- trueBody = _slang_gen_operation(A, &oper->children[1]);
- tree = new_seq(ifNode, trueBody);
-
- if (haveElseClause) {
- elseNode = new_else(ifNode);
- tree = new_seq(tree, elseNode);
-
- falseBody = _slang_gen_operation(A, &oper->children[2]);
- tree = new_seq(tree, falseBody);
- }
+ ifBody = _slang_gen_operation(A, &oper->children[1]);
+ if (haveElseClause)
+ elseBody = _slang_gen_operation(A, &oper->children[2]);
+ else
+ elseBody = NULL;
- endifNode = new_endif(haveElseClause ? elseNode : ifNode);
- tree = new_seq(tree, endifNode);
+ ifNode = new_if(cond, ifBody, elseBody);
- return tree;
+ return ifNode;
}
{ IR_CJUMP0, "IR_CJUMP0", OPCODE_NOP, 0, 0 },
{ IR_CJUMP1, "IR_CJUMP1", OPCODE_NOP, 0, 0 },
{ IR_IF, "IR_IF", OPCODE_NOP, 0, 0 },
- { IR_ELSE, "IR_ELSE", OPCODE_NOP, 0, 0 },
- { IR_ENDIF, "IR_ENDIF", OPCODE_NOP, 0, 0 },
{ IR_KILL, "IR_KILL", OPCODE_NOP, 0, 0 },
{ IR_COND, "IR_COND", OPCODE_NOP, 0, 0 },
{ IR_CALL, "IR_CALL", OPCODE_NOP, 0, 0 },
}
+static void
+spaces(int n)
+{
+ while (n-- > 0) {
+ printf(" ");
+ }
+}
+
#define IND 0
void
slang_print_ir(const slang_ir_node *n, int indent)
{
- int i;
if (!n)
return;
#if !IND
#else
printf("%3d:", indent);
#endif
- for (i = 0; i < indent; i++)
- printf(" ");
+ spaces(indent);
switch (n->Opcode) {
case IR_SEQ:
case IR_IF:
printf("IF \n");
slang_print_ir(n->Children[0], indent+3);
- break;
- case IR_ELSE:
- printf("ELSE\n");
- break;
- case IR_ENDIF:
+ spaces(indent);
+ printf("THEN\n");
+ slang_print_ir(n->Children[1], indent+3);
+ if (n->Children[2]) {
+ spaces(indent);
+ printf("ELSE\n");
+ slang_print_ir(n->Children[2], indent+3);
+ }
printf("ENDIF\n");
break;
}
+static struct prog_instruction *
+emit_if(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
+{
+ struct prog_instruction *ifInst;
+ GLuint ifInstLoc, elseInstLoc;
+
+ emit(vt, n->Children[0], prog); /* the condition */
+ ifInstLoc = prog->NumInstructions;
+ ifInst = new_instruction(prog, OPCODE_IF);
+ ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */
+ ifInst->DstReg.CondSwizzle = SWIZZLE_X;
+
+ /* if body */
+ emit(vt, n->Children[1], prog);
+
+ if (n->Children[2]) {
+ /* else body */
+ elseInstLoc = prog->NumInstructions;
+ (void) new_instruction(prog, OPCODE_ELSE);
+ ifInst = prog->Instructions + ifInstLoc;
+ ifInst->BranchTarget = prog->NumInstructions;
+
+ emit(vt, n->Children[2], prog);
+ }
+ else {
+ ifInst = prog->Instructions + ifInstLoc;
+ ifInst->BranchTarget = prog->NumInstructions + 1;
+ }
+
+ (void) new_instruction(prog, OPCODE_ENDIF);
+ if (n->Children[2]) {
+ struct prog_instruction *elseInst;
+ elseInst = prog->Instructions + elseInstLoc;
+ elseInst->BranchTarget = prog->NumInstructions;
+ }
+ return NULL;
+}
+
/**
* Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term).
return emit_kill(prog);
case IR_IF:
- {
- struct prog_instruction *inst;
- emit(vt, n->Children[0], prog); /* the condition */
- 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, *ifInst;
- 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);
- ifInst = prog->Instructions + n->BranchNode->InstLocation;
- assert(ifInst->Opcode == OPCODE_IF);
- ifInst->BranchTarget = prog->NumInstructions;
- return inst;
- }
- case IR_ENDIF:
- {
- struct prog_instruction *inst, *elseInst;
- 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);
- elseInst = prog->Instructions + n->BranchNode->InstLocation;
- assert(elseInst->Opcode == OPCODE_ELSE ||
- elseInst->Opcode == OPCODE_IF);
- elseInst->BranchTarget = prog->NumInstructions;
- return inst;
- }
+ return emit_if(vt, n, prog);
case IR_BEGIN_LOOP:
{