glsl: implement _slang_gen_while_without_continue()
authorBrian Paul <brianp@vmware.com>
Tue, 23 Jun 2009 20:05:11 +0000 (14:05 -0600)
committerBrian Paul <brianp@vmware.com>
Fri, 26 Jun 2009 19:16:33 +0000 (13:16 -0600)
src/mesa/shader/slang/slang_codegen.c

index 787bdb59c7bb52b3b0e5bf17ac781a599e34a01a..2c43e53b191d9e905183425b3541195c3a2d896f 100644 (file)
@@ -2411,14 +2411,102 @@ _slang_loop_contains_continue_or_break(const slang_operation *oper)
 }
 
 
+/**
+ * Replace 'break' and 'continue' statements inside a do and while loops.
+ * This is a recursive helper function used by
+ * _slang_gen_do/while_without_continue().
+ */
+static void
+replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
+{
+   switch (oper->type) {
+   case SLANG_OPER_BREAK:
+      /* replace 'break' with "_notBreakFlag = false; break" */
+      {
+         slang_operation *block = oper;
+         block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
+         slang_operation_add_children(block, 2);
+         {
+            slang_operation *assign = slang_oper_child(block, 0);
+            assign->type = SLANG_OPER_ASSIGN;
+            slang_operation_add_children(assign, 2);
+            {
+               slang_operation *lhs = slang_oper_child(assign, 0);
+               slang_operation_identifier(lhs, A, "_notBreakFlag");
+            }
+            {
+               slang_operation *rhs = slang_oper_child(assign, 1);
+               slang_operation_literal_bool(rhs, GL_FALSE);
+            }
+         }
+         {
+            slang_operation *brk = slang_oper_child(block, 1);
+            brk->type = SLANG_OPER_BREAK;
+            assert(!brk->children);
+         }
+      }
+      break;
+   case SLANG_OPER_CONTINUE:
+      /* convert continue into a break */
+      oper->type = SLANG_OPER_BREAK;
+      break;
+   case SLANG_OPER_FOR:
+   case SLANG_OPER_DO:
+   case SLANG_OPER_WHILE:
+      /* stop upon finding a nested loop */
+      break;
+   default:
+      /* recurse */
+      {
+         GLuint i;
+         for (i = 0; i < oper->num_children; i++) {
+            replace_break_and_cont(A, slang_oper_child(oper, i));
+         }
+      }
+   }
+}
+
+
+/**
+ * Transform a while-loop so that continue statements are converted to breaks.
+ * Then do normal IR code generation.
+ *
+ * Before:
+ * 
+ * while (LOOPCOND) {
+ *    A;
+ *    if (IFCOND)
+ *       continue;
+ *    B;
+ *    break;
+ *    C;
+ * }
+ * 
+ * After:
+ * 
+ * {
+ *    bool _notBreakFlag = 1;
+ *    while (_notBreakFlag && LOOPCOND) {
+ *       do {
+ *          A;
+ *          if (IFCOND) {
+ *             break;  // was continue
+ *          }
+ *          B;
+ *          _notBreakFlag = 0; // was
+ *          break;             // break
+ *          C;
+ *       } while (0)
+ *    }
+ * }
+ */
 static slang_ir_node *
 _slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
 {
-#if 0
    slang_operation *top;
    slang_operation *innerBody;
 
-   assert(oper->type == SLANG_OPER_DO);
+   assert(oper->type == SLANG_OPER_WHILE);
 
    top = slang_operation_new(1);
    top->type = SLANG_OPER_BLOCK_NEW_SCOPE;
@@ -2440,21 +2528,36 @@ _slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
       slang_operation_literal_bool(var->initializer, GL_TRUE);
    }
 
-   /* build outer do-loop:  do { ... } while (_notBreakFlag && LOOPCOND) */
+   /* build outer while-loop:  while (_notBreakFlag && LOOPCOND) { ... } */
    {
-      slang_operation *outerDo = slang_oper_child(top, 1);
-      outerDo->type = SLANG_OPER_DO;
-      slang_operation_add_children(outerDo, 2);
+      slang_operation *outerWhile = slang_oper_child(top, 1);
+      outerWhile->type = SLANG_OPER_WHILE;
+      slang_operation_add_children(outerWhile, 2);
 
-      /* inner do-loop */
+      /* _notBreakFlag && LOOPCOND */
       {
-         slang_operation *innerDo = slang_oper_child(outerDo, 0);
+         slang_operation *cond = slang_oper_child(outerWhile, 0);
+         cond->type = SLANG_OPER_LOGICALAND;
+         slang_operation_add_children(cond, 2);
+         {
+            slang_operation *notBreak = slang_oper_child(cond, 0);
+            slang_operation_identifier(notBreak, A, "_notBreakFlag");
+         }
+         {
+            slang_operation *origCond = slang_oper_child(cond, 1);
+            slang_operation_copy(origCond, slang_oper_child(oper, 0));
+         }
+      }
+
+      /* inner loop */
+      {
+         slang_operation *innerDo = slang_oper_child(outerWhile, 1);
          innerDo->type = SLANG_OPER_DO;
          slang_operation_add_children(innerDo, 2);
 
          /* copy original do-loop body into inner do-loop's body */
          innerBody = slang_oper_child(innerDo, 0);
-         slang_operation_copy(innerBody, slang_oper_child(oper, 0));
+         slang_operation_copy(innerBody, slang_oper_child(oper, 1));
          innerBody->locals->outer_scope = innerDo->locals;
 
          /* inner do-loop's condition is constant/false */
@@ -2463,21 +2566,6 @@ _slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
             slang_operation_literal_bool(constFalse, GL_FALSE);
          }
       }
-
-      /* _notBreakFlag && LOOPCOND */
-      {
-         slang_operation *cond = slang_oper_child(outerDo, 1);
-         cond->type = SLANG_OPER_LOGICALAND;
-         slang_operation_add_children(cond, 2);
-         {
-            slang_operation *notBreak = slang_oper_child(cond, 0);
-            slang_operation_identifier(notBreak, A, "_notBreakFlag");
-         }
-         {
-            slang_operation *origCond = slang_oper_child(cond, 1);
-            slang_operation_copy(origCond, slang_oper_child(oper, 1));
-         }
-      }
    }
 
    /* Finally, in innerBody,
@@ -2486,10 +2574,10 @@ _slang_gen_while_without_continue(slang_assemble_ctx *A, slang_operation *oper)
     */
    replace_break_and_cont(A, innerBody);
 
-   slang_print_tree(top, 0);
+   /*slang_print_tree(top, 0);*/
 
    return _slang_gen_operation(A, top);
-#endif
+
    return NULL;
 }
 
@@ -2569,61 +2657,6 @@ _slang_gen_while(slang_assemble_ctx * A, slang_operation *oper)
 }
 
 
-/**
- * Replace 'break' and 'continue' statements inside a do-while loop.
- * This is a recursive helper function used by _slang_gen_do_without_continue().
- */
-static void
-replace_break_and_cont(slang_assemble_ctx *A, slang_operation *oper)
-{
-   switch (oper->type) {
-   case SLANG_OPER_BREAK:
-      /* replace 'break' with "_notBreakFlag = false; break" */
-      {
-         slang_operation *block = oper;
-         block->type = SLANG_OPER_BLOCK_NEW_SCOPE;
-         slang_operation_add_children(block, 2);
-         {
-            slang_operation *assign = slang_oper_child(block, 0);
-            assign->type = SLANG_OPER_ASSIGN;
-            slang_operation_add_children(assign, 2);
-            {
-               slang_operation *lhs = slang_oper_child(assign, 0);
-               slang_operation_identifier(lhs, A, "_notBreakFlag");
-            }
-            {
-               slang_operation *rhs = slang_oper_child(assign, 1);
-               slang_operation_literal_bool(rhs, GL_FALSE);
-            }
-         }
-         {
-            slang_operation *brk = slang_oper_child(block, 1);
-            brk->type = SLANG_OPER_BREAK;
-            assert(!brk->children);
-         }
-      }
-      break;
-   case SLANG_OPER_CONTINUE:
-      /* convert continue into a break */
-      oper->type = SLANG_OPER_BREAK;
-      break;
-   case SLANG_OPER_FOR:
-   case SLANG_OPER_DO:
-   case SLANG_OPER_WHILE:
-      /* stop upon finding a nested loop */
-      break;
-   default:
-      /* recurse */
-      {
-         GLuint i;
-         for (i = 0; i < oper->num_children; i++) {
-            replace_break_and_cont(A, slang_oper_child(oper, i));
-         }
-      }
-   }
-}
-
-
 /**
  * Transform a do-while-loop so that continue statements are converted to breaks.
  * Then do normal IR code generation.
@@ -2731,7 +2764,7 @@ _slang_gen_do_without_continue(slang_assemble_ctx *A, slang_operation *oper)
     */
    replace_break_and_cont(A, innerBody);
 
-   slang_print_tree(top, 0);
+   /*slang_print_tree(top, 0);*/
 
    return _slang_gen_operation(A, top);
 }