summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/shader/prog_print.c10
-rw-r--r--src/mesa/shader/slang/slang_codegen.c29
-rw-r--r--src/mesa/shader/slang/slang_emit.c47
-rw-r--r--src/mesa/swrast/s_fragprog.c6
4 files changed, 74 insertions, 18 deletions
diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 3d4a474b052..6c303de9b5a 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -338,8 +338,14 @@ _mesa_print_instruction(const struct prog_instruction *inst, GLint indent)
_mesa_printf("ENDLOOP (goto %d)\n", inst->BranchTarget);
break;
case OPCODE_BRK:
- /* XXX just like BRA */
- _mesa_printf("BRK (%s%s) (for loop beginning at %d)",
+ _mesa_printf("BRK (%s%s) (goto %d)",
+ condcode_string(inst->DstReg.CondMask),
+ swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
+ inst->BranchTarget);
+ print_comment(inst);
+ break;
+ case OPCODE_CONT:
+ _mesa_printf("CONT (%s%s) (goto %d)",
condcode_string(inst->DstReg.CondMask),
swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
inst->BranchTarget);
diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index a4e2935ea84..42c1f0897eb 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -608,7 +608,24 @@ new_break(slang_ir_node *loopNode)
assert(loopNode);
assert(loopNode->Opcode == IR_LOOP);
if (n) {
- n->BranchNode = loopNode;
+ /* insert this node at head of linked list */
+ n->BranchNode = loopNode->BranchNode;
+ loopNode->BranchNode = n;
+ }
+ return n;
+}
+
+
+static slang_ir_node *
+new_cont(slang_ir_node *loopNode)
+{
+ slang_ir_node *n = new_node0(IR_CONT);
+ assert(loopNode);
+ assert(loopNode->Opcode == IR_LOOP);
+ if (n) {
+ /* insert this node at head of linked list */
+ n->BranchNode = loopNode->BranchNode;
+ loopNode->BranchNode = n;
}
return n;
}
@@ -2434,11 +2451,15 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
return new_jump(A->CurLoopBreak);
}
case slang_oper_continue:
- if (!A->CurLoopCont) {
+ if (!A->CurLoop && !A->CurLoopCont) {
RETURN_ERROR("'continue' not in loop", 0);
}
- /* XXX emit IR_CONT instruction */
- return new_jump(A->CurLoopCont);
+ if (UseHighLevelInstructions) {
+ return new_cont(A->CurLoop);
+ }
+ else {
+ return new_jump(A->CurLoopCont);
+ }
case slang_oper_discard:
return new_node0(IR_KILL);
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index c18f1e364ce..2d5a7cf6f9d 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -1303,7 +1303,9 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
case IR_LOOP:
{
- struct prog_instruction *beginInst;
+ struct prog_instruction *beginInst, *endInst;
+ GLuint endInstLoc;
+ slang_ir_node *p;
/* save location of this instruction, used by OPCODE_ENDLOOP */
n->InstLocation = prog->NumInstructions;
@@ -1312,27 +1314,48 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
/* body */
emit(vt, n->Children[0], prog);
- inst = new_instruction(prog, OPCODE_ENDLOOP);
- /* The instruction BranchTarget points to top of loop */
- inst->BranchTarget = n->InstLocation;
+ endInstLoc = prog->NumInstructions;
+ endInst = new_instruction(prog, OPCODE_ENDLOOP);
+ /* The ENDLOOP's BranchTarget points to top of loop */
+ endInst->BranchTarget = n->InstLocation;
/* Update BGNLOOP's BranchTarget to point to this instruction */
beginInst = prog->Instructions + n->InstLocation;
beginInst->BranchTarget = prog->NumInstructions - 1;
- return inst;
+
+ /* Done emitting loop code. Now walk over the loop's linked list
+ * of BREAK and CONT nodes, filling in their BranchTarget fields.
+ */
+ for (p = n->BranchNode; p; p = p->BranchNode) {
+ if (p->Opcode == IR_BREAK) {
+ struct prog_instruction *brkInst
+ = prog->Instructions + p->InstLocation;
+ assert(brkInst->Opcode == OPCODE_BRK);
+ brkInst->BranchTarget = endInstLoc + 1;
+ }
+ else {
+ assert(p->Opcode == IR_CONT);
+ struct prog_instruction *contInst
+ = prog->Instructions + p->InstLocation;
+ assert(contInst->Opcode == OPCODE_CONT);
+ contInst->BranchTarget = endInstLoc;
+ }
+ }
+ return NULL;
}
case IR_CONT:
- return new_instruction(prog, OPCODE_CONT);
+ {
+ struct prog_instruction *inst;
+ n->InstLocation = prog->NumInstructions;
+ inst = new_instruction(prog, OPCODE_CONT);
+ inst->DstReg.CondMask = COND_TR; /* always true */
+ return inst;
+ }
case IR_BREAK:
{
struct prog_instruction *inst;
+ n->InstLocation = prog->NumInstructions;
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;
}
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index 12c8aee6ea0..63974b30f20 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -704,6 +704,7 @@ execute_program( GLcontext *ctx,
break;
case OPCODE_BRK: /* break out of loop */
{
+#if 0
/* The location of the ENDLOOP instruction is saved in the
* BGNLOOP instruction. Get that instruction and jump to
* its BranchTarget + 1.
@@ -714,6 +715,9 @@ execute_program( GLcontext *ctx,
ASSERT(loopBeginInst->BranchTarget >= 0);
/* we'll add one at bottom of for-loop */
pc = loopBeginInst->BranchTarget;
+#else
+ pc = inst->BranchTarget - 1;
+#endif
}
break;
case OPCODE_CAL: /* Call subroutine */
@@ -747,6 +751,8 @@ execute_program( GLcontext *ctx,
}
break;
case OPCODE_CONT: /* continue loop */
+ /* Subtract 1 here since we'll do pc++ at end of for-loop */
+ pc = inst->BranchTarget - 1;
break;
case OPCODE_COS:
{