replace IR_BEGIN_LOOP/IR_END_LOOP with IR_LOOP
authorBrian <brian@nostromo.localnet.net>
Wed, 7 Feb 2007 04:33:29 +0000 (21:33 -0700)
committerBrian <brian@nostromo.localnet.net>
Wed, 7 Feb 2007 04:33:29 +0000 (21:33 -0700)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.h
src/mesa/shader/slang/slang_typeinfo.h

index 88d61a5a68166ad6d4514f426ee99c924ac9a677..a4e2935ea84eb3fa0f830b5a291919c3aa1cdbce 100644 (file)
@@ -490,10 +490,12 @@ static void
 _slang_free_ir_tree(slang_ir_node *n)
 {
 #if 0
+   GLuint i;
    if (!n)
       return;
-   _slang_free_ir_tree(n->Children[0]);
-   _slang_free_ir_tree(n->Children[1]);
+   for (i = 0; i < 3; i++)
+      _slang_free_ir_tree(n->Children[i]);
+   /* Do not free n->BranchNode since it's a child elsewhere */
    free(n);
 #endif
 }
@@ -537,9 +539,10 @@ new_node0(slang_ir_opcode op)
 static slang_ir_node *
 new_seq(slang_ir_node *left, slang_ir_node *right)
 {
-   /* XXX if either left or right is null, just return pointer to other?? */
-   assert(left);
-   assert(right);
+   if (!left)
+      return right;
+   if (!right)
+      return left;
    return new_node2(IR_SEQ, left, right);
 }
 
@@ -592,32 +595,20 @@ new_jump(slang_atom target)
 
 
 static slang_ir_node *
-new_begin_loop(void)
-{
-   slang_ir_node *n = new_node0(IR_BEGIN_LOOP);
-   return n;
-}
-
-
-static slang_ir_node *
-new_end_loop(slang_ir_node *beginNode)
+new_loop(slang_ir_node *body)
 {
-   slang_ir_node *n = new_node0(IR_END_LOOP);
-   assert(beginNode);
-   if (n) {
-      n->BranchNode = beginNode;
-   }
-   return n;
+   return new_node1(IR_LOOP, body);
 }
 
 
 static slang_ir_node *
-new_break(slang_ir_node *beginNode)
+new_break(slang_ir_node *loopNode)
 {
    slang_ir_node *n = new_node0(IR_BREAK);
-   assert(beginNode);
+   assert(loopNode);
+   assert(loopNode->Opcode == IR_LOOP);
    if (n) {
-      n->BranchNode = beginNode;
+      n->BranchNode = loopNode;
    }
    return n;
 }
@@ -1415,43 +1406,43 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
 
 
 /**
- * Generate IR tree for a while-loop using high-level BGNLOOP/ENDLOOP,
- * IF/ENDIF instructions.
+ * Generate IR tree for a while-loop using high-level LOOP, IF instructions.
  */
 static slang_ir_node *
 _slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
 {
+   slang_ir_node *prevLoop;
    /*
-    * BGNLOOP
+    * LOOP:
     *    eval expr (child[0]), updating condcodes
-    *    IF !expr THEN
+    *    IF !expr:
     *       BRK
-    *    ENDIF
     *    body code (child[1])
-    * ENDLOOP
     */
-   slang_ir_node *beginLoop, *endLoop, *ifThen;
-   slang_ir_node *cond, *body, *tree;
+   slang_ir_node *ifThen, *cond, *body, *loop;
 
-   beginLoop = new_begin_loop();
+   loop = new_loop(NULL);
+
+   /* save old, push new loop */
+   prevLoop = A->CurLoop;
+   A->CurLoop = loop;
 
    cond = _slang_gen_operation(A, &oper->children[0]);
    cond = new_node1(IR_NOT, cond);
    cond = _slang_gen_cond(cond);
 
    ifThen = new_if(cond,
-                   new_break(beginLoop),
+                   new_break(A->CurLoop),
                    NULL);
-   tree = new_seq(beginLoop, ifThen);
 
    body = _slang_gen_operation(A, &oper->children[1]);
-   if (body)
-      tree = new_seq(tree, body);
 
-   endLoop = new_end_loop(beginLoop);
-   tree = new_seq(tree, endLoop);
+   loop->Children[0] = new_seq(ifThen, body);
 
-   return tree;
+
+   A->CurLoop = prevLoop; /* pop loop, restore prev */
+
+   return loop;
 }
 
 
@@ -2433,11 +2424,15 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
       else
          return _slang_gen_for(A, oper);
    case slang_oper_break:
-      if (!A->CurLoopBreak) {
+      if (!A->CurLoop && !A->CurLoopBreak) {
          RETURN_ERROR("'break' not in loop", 0);
       }
-      /* XXX emit IR_BREAK instruction */
-      return new_jump(A->CurLoopBreak);
+      if (UseHighLevelInstructions) {
+         return new_break(A->CurLoop);
+      }
+      else {
+         return new_jump(A->CurLoopBreak);
+      }
    case slang_oper_continue:
       if (!A->CurLoopCont) {
          RETURN_ERROR("'continue' not in loop", 0);
index 82a8f0befb4ea6942331eedbabd86582f54236f0..c18f1e364ce3dfe9f64321b8f9afcd3a52437444 100644 (file)
@@ -317,11 +317,11 @@ slang_print_ir(const slang_ir_node *n, int indent)
       printf("CALL\n");
       break;
 
-   case IR_BEGIN_LOOP:
-      printf("BEGIN_LOOP\n");
-      break;
-   case IR_END_LOOP:
-      printf("END_LOOP\n");
+   case IR_LOOP:
+      printf("LOOP\n");
+      slang_print_ir(n->Children[0], indent+3);
+      spaces(indent);
+      printf("ENDLOOP\n");
       break;
    case IR_CONT:
       printf("CONT\n");
@@ -1301,23 +1301,22 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
    case IR_IF:
       return emit_if(vt, n, prog);
 
-   case IR_BEGIN_LOOP:
+   case IR_LOOP:
       {
+         struct prog_instruction *beginInst;
+
          /* save location of this instruction, used by OPCODE_ENDLOOP */
          n->InstLocation = prog->NumInstructions;
          (void) new_instruction(prog, OPCODE_BGNLOOP);
-      }
-      break;
-   case IR_END_LOOP:
-      {
-         struct prog_instruction *inst, *beginInst;
+
+         /* body */
+         emit(vt, n->Children[0], prog);
+
          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;
+         inst->BranchTarget = n->InstLocation;
+         /* Update BGNLOOP's BranchTarget to point to this instruction */
+         beginInst = prog->Instructions + n->InstLocation;
          beginInst->BranchTarget = prog->NumInstructions - 1;
          return inst;
       }
@@ -1336,6 +1335,7 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
          inst->BranchTarget = n->BranchNode->InstLocation;
          return inst;
       }
+
    case IR_BEGIN_SUB:
       return new_instruction(prog, OPCODE_BGNSUB);
    case IR_END_SUB:
@@ -1343,6 +1343,9 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
    case IR_RETURN:
       return new_instruction(prog, OPCODE_RET);
 
+   case IR_NOP:
+      return NULL;
+
    default:
       _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");
       abort();
index 0f2ceb03c07fc5d9076e7cd0f2e790e05563b7e2..a7c858c69f748093aef572a6e1aaf60e7ee0c409 100644 (file)
@@ -60,8 +60,7 @@ typedef enum
    IR_RETURN,    /* return from subroutine */
    IR_CALL,      /* call subroutine */
 
-   IR_BEGIN_LOOP,/* begin loop */
-   IR_END_LOOP,  /* end loop */
+   IR_LOOP,      /* high-level loop-begin / loop-end */
    IR_CONT,      /* continue loop */
    IR_BREAK,     /* break loop */
 
index 6e27079ff897d66a7a643eae4e9f268b707497c4..d23bb6be146a9589d0944f368fd7b4e01b0cf5a8 100644 (file)
@@ -63,6 +63,7 @@ typedef struct slang_assemble_ctx_
    struct slang_function_ *CurFunction;
    slang_atom CurLoopBreak;
    slang_atom CurLoopCont;
+   struct slang_ir_node_ *CurLoop;
 } slang_assemble_ctx;