Implement do/while loops. Replace IR_CJUMP with IR_CJUMP0 and IR_CJUMP1 so
authorBrian <brian@yutani.localnet.net>
Fri, 19 Jan 2007 20:13:15 +0000 (13:13 -0700)
committerBrian <brian@yutani.localnet.net>
Fri, 19 Jan 2007 20:13:15 +0000 (13:13 -0700)
we can either jump on zero, or non-zero predicate.

src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.h

index 76dcca576d2c6742e524bf2e62b3d4fada10ad8f..60bf57035f09c8cf525cfb0121481f506dfaa714 100644 (file)
@@ -562,18 +562,22 @@ new_float_literal(float x, float y, float z, float w)
 }
 
 /**
+ * Conditional jump.
+ * \param zeroOrOne indicates if the jump is to be taken on zero, or non-zero
+ *                  condition code state.
  * XXX maybe pass an IR node as second param to indicate the jump target???
  */
 static slang_ir_node *
-new_cjump(slang_atom target)
+new_cjump(slang_atom target, GLuint zeroOrOne)
 {
-   slang_ir_node *n = new_node(IR_CJUMP, NULL, NULL);
+   slang_ir_node *n = new_node(zeroOrOne ? IR_CJUMP1 : IR_CJUMP0, NULL, NULL);
    if (n)
       n->Target = (char *) target;
    return n;
 }
 
 /**
+ * Unconditional jump.
  * XXX maybe pass an IR node as second param to indicate the jump target???
  */
 static slang_ir_node *
@@ -1386,7 +1390,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
    cond = _slang_gen_cond(cond);
    tree = new_seq(startLab, cond);
 
-   bra = new_cjump(endAtom);
+   bra = new_cjump(endAtom, 0);
    tree = new_seq(tree, bra);
 
    body = _slang_gen_operation(A, &oper->children[1]);
@@ -1406,6 +1410,52 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
 }
 
 
+/**
+ * Generate IR tree for a do-while-loop.
+ */
+static slang_ir_node *
+_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   /*
+    * label "__startDo"
+    * code body
+    * eval expr (child[0]), updating condcodes
+    * branch if true to "__startDo"
+    * label "__endDo"
+    */
+   slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startDo");
+   slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endDo");
+   slang_ir_node *startLab, *cond, *bra, *body, *endLab, *tree;
+   slang_atom prevLoopBreak = A->CurLoopBreak;
+   slang_atom prevLoopCont = A->CurLoopCont;
+
+   /* Push this loop */
+   A->CurLoopBreak = endAtom;
+   A->CurLoopCont = startAtom;
+
+   startLab = new_label(startAtom);
+
+   body = _slang_gen_operation(A, &oper->children[0]);
+   tree = new_seq(startLab, body);
+
+   cond = _slang_gen_operation(A, &oper->children[1]);
+   cond = _slang_gen_cond(cond);
+   tree = new_seq(tree, cond);
+
+   bra = new_cjump(startAtom, 1);
+   tree = new_seq(tree, bra);
+
+   endLab = new_label(endAtom);
+   tree = new_seq(tree, endLab);
+
+   /* Pop this loop */
+   A->CurLoopBreak = prevLoopBreak;
+   A->CurLoopCont = prevLoopCont;
+
+   return tree;
+}
+
+
 /**
  * Generate IR tree for a for-loop.
  */
@@ -1443,7 +1493,7 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
    cond = _slang_gen_cond(cond);
    tree = new_seq(tree, cond);
 
-   bra = new_cjump(endAtom);
+   bra = new_cjump(endAtom, 0);
    tree = new_seq(tree, bra);
 
    body = _slang_gen_operation(A, &oper->children[3]);
@@ -1493,7 +1543,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
    cond = _slang_gen_operation(A, &oper->children[0]);
    cond = _slang_gen_cond(cond);
    /*assert(cond->Store);*/
-   bra = new_cjump(haveElseClause ? elseAtom : endifAtom);
+   bra = new_cjump(haveElseClause ? elseAtom : endifAtom, 0);
    tree = new_seq(cond, bra);
 
    trueBody = _slang_gen_operation(A, &oper->children[1]);
@@ -1593,8 +1643,8 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
    cond = _slang_gen_cond(cond);
    tree = new_seq(tmpDecl, cond);
 
-   /* jump if true to "alt" label */
-   cjump = new_cjump(altAtom);
+   /* jump if false to "alt" label */
+   cjump = new_cjump(altAtom, 0);
    tree = new_seq(tree, cjump);
 
    /* evaluate child 2 (y) and assign to tmp */
@@ -2042,6 +2092,8 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
       break;
    case slang_oper_while:
       return _slang_gen_while(A, oper);
+   case slang_oper_do:
+      return _slang_gen_do(A, oper);
    case slang_oper_for:
       return _slang_gen_for(A, oper);
    case slang_oper_break:
index c660f2ceac678bbebf3dc66274963af14ab382f9..9dda28d842eb6584796c1c82aebe329b98e5f740 100644 (file)
@@ -89,7 +89,8 @@ static slang_ir_info IrInfo[] = {
    { IR_SCOPE, "IR_SCOPE", 0, 0, 0 },
    { IR_LABEL, "IR_LABEL", 0, 0, 0 },
    { IR_JUMP, "IR_JUMP", 0, 0, 0 },
-   { IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
+   { IR_CJUMP0, "IR_CJUMP0", 0, 0, 0 },
+   { IR_CJUMP1, "IR_CJUMP1", 0, 0, 0 },
    { IR_KILL, "IR_KILL", 0, 0, 0 },
    { IR_COND, "IR_COND", 0, 0, 0 },
    { IR_CALL, "IR_CALL", 0, 0, 0 },
@@ -262,8 +263,12 @@ slang_print_ir(const slang_ir_node *n, int indent)
    case IR_JUMP:
       printf("JUMP %s\n", n->Target);
       break;
-   case IR_CJUMP:
-      printf("CJUMP %s\n", n->Target);
+   case IR_CJUMP0:
+      printf("CJUMP0 %s\n", n->Target);
+      slang_print_ir(n->Children[0], indent+3);
+      break;
+   case IR_CJUMP1:
+      printf("CJUMP1 %s\n", n->Target);
       slang_print_ir(n->Children[0], indent+3);
       break;
    case IR_VAR:
@@ -515,11 +520,14 @@ emit_label(const char *target, struct gl_program *prog)
 
 
 static struct prog_instruction *
-emit_cjump(const char *target, struct gl_program *prog)
+emit_cjump(const char *target, struct gl_program *prog, GLuint zeroOrOne)
 {
    struct prog_instruction *inst;
    inst = new_instruction(prog, OPCODE_BRA);
-   inst->DstReg.CondMask = COND_EQ;  /* branch if equal to zero */
+   if (zeroOrOne)
+      inst->DstReg.CondMask = COND_NE;  /* branch if non-zero */
+   else
+      inst->DstReg.CondMask = COND_EQ;  /* branch if equal to zero */
    inst->DstReg.CondSwizzle = SWIZZLE_X;
    inst->Comment = _mesa_strdup(target);
    return inst;
@@ -666,7 +674,7 @@ emit_cond(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
 {
    /* Conditional expression (in if/while/for stmts).
     * Need to update condition code register.
-    * Next instruction is typically an IR_CJUMP.
+    * Next instruction is typically an IR_CJUMP0/1.
     */
    /* last child expr instruction: */
    struct prog_instruction *inst = emit(vt, n->Children[0], prog);
@@ -842,8 +850,10 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
       return emit_label(n->Target, prog);
    case IR_JUMP:
       return emit_jump(n->Target, prog);
-   case IR_CJUMP:
-      return emit_cjump(n->Target, prog);
+   case IR_CJUMP0:
+      return emit_cjump(n->Target, prog, 0);
+   case IR_CJUMP1:
+      return emit_cjump(n->Target, prog, 1);
    case IR_KILL:
       return emit_kill(prog);
 
index a337d61712be7587f0256d583374a4b9e6a9a7e8..4072c70f902b69af9dc6f7b291df0474b1a315c9 100644 (file)
@@ -48,7 +48,8 @@ typedef enum
    IR_SCOPE,   /* new variable scope (one child) */
    IR_LABEL,   /* target of a jump or cjump */
    IR_JUMP,    /* unconditional jump */
-   IR_CJUMP,   /* conditional jump */
+   IR_CJUMP0,  /* conditional jump if zero */
+   IR_CJUMP1,  /* conditional jump if one (or non-zero) */
    IR_COND,    /* conditional expression */
    IR_CALL,    /* call subroutine */
    IR_MOVE,