Implement CONT, improve BRK.
authorBrian <brian@nostromo.localnet.net>
Wed, 7 Feb 2007 05:31:19 +0000 (22:31 -0700)
committerBrian <brian@nostromo.localnet.net>
Wed, 7 Feb 2007 05:31:19 +0000 (22:31 -0700)
IR_LOOP's BranchNode ptr is the head of a linked list of CONT and BRK nodes.
After emitting loop, walk over the linked list, filling in the CONT/BRK
instruction's BranchTarget field (location of the ENDLOOP instruction, or
one past).

src/mesa/shader/prog_print.c
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/swrast/s_fragprog.c

index 3d4a474b052a05fe191d3c1276def020c07e05b3..6c303de9b5a40bbe64227d10aecbcd68d6dd66a5 100644 (file)
@@ -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);
index a4e2935ea84eb3fa0f830b5a291919c3aa1cdbce..42c1f0897eb334a3ec4c44fc005b18976dff45d4 100644 (file)
@@ -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);
 
index c18f1e364ce3dfe9f64321b8f9afcd3a52437444..2d5a7cf6f9da82f21c029b853a965ae6bad92784 100644 (file)
@@ -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;
       }
 
index 12c8aee6ea0c5c38c8fb9991b2c95930081a7c98..63974b30f208e561ffe9b32086af9affb43bb889 100644 (file)
@@ -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:
             {