summaryrefslogtreecommitdiff
path: root/src/mesa/shader/slang/slang_emit.c
diff options
context:
space:
mode:
authorBrian <brian@yutani.localnet.net>2007-02-05 18:01:02 -0700
committerBrian <brian@yutani.localnet.net>2007-02-05 18:01:02 -0700
commit2755c798f3cb89fcd4ece16cd740af1cd86a6b99 (patch)
tree423205b0b37cf79f08f4b2b0a6d2a845e6f1dbc2 /src/mesa/shader/slang/slang_emit.c
parent86080796471df6a9e126fd536b21c3b10cb5310c (diff)
BRK instruction's BranchTarget field now used for efficiently breaking out of loops.
BRK's BranchTarget field actually points to the top of the loop, not the bottom, since we don't know the later's location yet. In the interpreter, basically do an indirect jump to update the PC.
Diffstat (limited to 'src/mesa/shader/slang/slang_emit.c')
-rw-r--r--src/mesa/shader/slang/slang_emit.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index b890a6d93c..3faacdd4cf 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -1265,24 +1265,29 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
}
case IR_ELSE:
{
- struct prog_instruction *inst;
+ 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);
- prog->Instructions[n->BranchNode->InstLocation].BranchTarget = prog->NumInstructions;
+ ifInst = prog->Instructions + n->BranchNode->InstLocation;
+ assert(ifInst->Opcode == OPCODE_IF);
+ ifInst->BranchTarget = prog->NumInstructions;
return inst;
}
case IR_ENDIF:
{
- struct prog_instruction *inst;
+ 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);
- prog->Instructions[n->BranchNode->InstLocation].BranchTarget = prog->NumInstructions;
+ elseInst = prog->Instructions + n->BranchNode->InstLocation;
+ assert(elseInst->Opcode == OPCODE_ELSE ||
+ elseInst->Opcode == OPCODE_IF);
+ elseInst->BranchTarget = prog->NumInstructions;
return inst;
}
@@ -1295,12 +1300,15 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
break;
case IR_END_LOOP:
{
- struct prog_instruction *inst;
+ struct prog_instruction *inst, *beginInst;
inst = new_instruction(prog, OPCODE_ENDLOOP);
assert(n->BranchNode);
assert(n->BranchNode->InstLocation >= 0);
/* The instruction BranchTarget points to top of loop */
inst->BranchTarget = n->BranchNode->InstLocation;
+ /* Update BEGIN_LOOP's BranchTarget to point to this instruction */
+ beginInst = prog->Instructions + n->BranchNode->InstLocation;
+ beginInst->BranchTarget = prog->NumInstructions - 1;
return inst;
}
case IR_CONT:
@@ -1310,6 +1318,12 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
struct prog_instruction *inst;
inst = new_instruction(prog, OPCODE_BRK);
inst->DstReg.CondMask = COND_TR; /* always true */
+ /* This instruction's branch target is top of loop, not bottom of
+ * loop because we don't know where it is yet!
+ */
+ assert(n->BranchNode);
+ assert(n->BranchNode->InstLocation >= 0);
+ inst->BranchTarget = n->BranchNode->InstLocation;
return inst;
}
case IR_BEGIN_SUB: