Use IR node's BranchNode field for IF/ELSE/ENDIF instructions.
authorBrian <brian@yutani.localnet.net>
Tue, 6 Feb 2007 00:18:10 +0000 (17:18 -0700)
committerBrian <brian@yutani.localnet.net>
Tue, 6 Feb 2007 00:18:10 +0000 (17:18 -0700)
This allows us to back-patch the IF/ELSE instruction's BranchTarget field
to point to the location of the ELSE/ENDIF instructions.  No longer have to
search for ELSE/ENDIF in the interpreter.  Also makes it trivial to translate
IF/ELSE instructions into conditional/unconditional BRA instructions.

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 208c998661c1b2a17d408f7c6878020989a20fe4..aea11da0db5b7c29c3a0264be58e81ce69f5b3d2 100644 (file)
@@ -319,13 +319,14 @@ _mesa_print_instruction(const struct prog_instruction *inst, GLint indent)
       print_comment(inst);
       break;
    case OPCODE_IF:
-      _mesa_printf("IF (%s%s)",
+      _mesa_printf("IF (%s%s) (if false, goto %d)",
                    condcode_string(inst->DstReg.CondMask),
-                   swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE));
+                   swizzle_string(inst->DstReg.CondSwizzle, 0, GL_FALSE),
+                   inst->BranchTarget);
       print_comment(inst);
       return indent + 3;
    case OPCODE_ELSE:
-      _mesa_printf("ELSE\n");
+      _mesa_printf("ELSE (goto %d)\n", inst->BranchTarget);
       return indent + 3;
    case OPCODE_ENDIF:
       _mesa_printf("ENDIF\n");
index c70f73f15a829d6c2400136c9ec4f50e0d8fafb5..7a1881c68ee084c5eecd4b9e881b636a1d98201a 100644 (file)
@@ -590,6 +590,47 @@ new_end_loop(slang_ir_node *beginNode)
 }
 
 
+/**
+ * Child[0] is the condition.
+ * XXX we might re-design IR_IF so Children[1] is the "then" body and
+ * Children[0] is the "else" body.
+ */
+static slang_ir_node *
+new_if(slang_ir_node *cond)
+{
+   slang_ir_node *n = new_node(IR_IF, NULL, NULL);
+   assert(cond);
+   if (n) {
+      n->Children[0] = cond;
+   }
+   return n;
+}
+
+
+static slang_ir_node *
+new_else(slang_ir_node *ifNode)
+{
+   slang_ir_node *n = new_node(IR_ELSE, NULL, NULL);
+   assert(ifNode);
+   if (n) {
+      n->BranchNode = ifNode;
+   }
+   return n;
+}
+
+
+static slang_ir_node *
+new_endif(slang_ir_node *elseOrIfNode)
+{
+   slang_ir_node *n = new_node(IR_ENDIF, NULL, NULL);
+   assert(elseOrIfNode);
+   if (n) {
+      n->BranchNode = elseOrIfNode;
+   }
+   return n;
+}
+
+
 /**
  * New IR_VAR node - a reference to a previously declared variable.
  */
@@ -1401,13 +1442,13 @@ _slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
    cond = new_node(IR_NOT, cond, NULL);
    cond = _slang_gen_cond(cond);
 
-   ifThen = new_node(IR_IF, cond, NULL);
+   ifThen = new_if(cond);
    tree = new_seq(beginLoop, ifThen);
 
    brk = new_node(IR_BREAK, NULL, NULL);
    tree = new_seq(tree, brk);
 
-   endif = new_node(IR_ENDIF, NULL, NULL);
+   endif = new_endif(ifThen);
    tree = new_seq(tree, endif);
 
    body = _slang_gen_operation(A, &oper->children[1]);
@@ -1589,13 +1630,11 @@ _slang_gen_hl_if(slang_assemble_ctx * A, const slang_operation *oper)
 {
    /*
     * eval expr (child[0]), updating condcodes
-    * branch if false to _else or _endif
-    * "true" code block
-    * if haveElseClause clause:
-    *    jump "__endif"
-    *    label "__else"
-    *    "false" code block
-    * label "__endif"
+    * IF expr THEN
+    *    if-body code
+    * ELSE
+    *    else-body code
+    * ENDIF
     */
    /* XXX special cases to check for:
     * if body of conditiona is just a "break", emit a conditional break
@@ -1608,21 +1647,20 @@ _slang_gen_hl_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);*/
-   ifNode = new_node(IR_IF, cond, NULL);
+   ifNode = new_if(cond);
 
    trueBody = _slang_gen_operation(A, &oper->children[1]);
    tree = new_seq(ifNode, trueBody);
 
    if (haveElseClause) {
-      /* else clause */
-      elseNode = new_node(IR_ELSE, NULL, NULL);
+      elseNode = new_else(ifNode);
       tree = new_seq(tree, elseNode);
 
       falseBody = _slang_gen_operation(A, &oper->children[2]);
       tree = new_seq(tree, falseBody);
    }
 
-   endifNode = new_node(IR_ENDIF, NULL, NULL);
+   endifNode = new_endif(haveElseClause ? elseNode : ifNode);
    tree = new_seq(tree, endifNode);
 
    return tree;
index 311eea1e6ad725cfcd6c003d8a16b4bd0a62d956..b890a6d93c29c5603aee748a6be2b6738f577ffa 100644 (file)
@@ -1036,6 +1036,7 @@ emit_not(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
 
    free_temp_storage(vt, n->Children[0]);
 
+   inst->Comment = _mesa_strdup("NOT");
    return inst;
 }
 
@@ -1259,18 +1260,29 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
          inst = new_instruction(prog, OPCODE_IF);
          inst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
          inst->DstReg.CondSwizzle = SWIZZLE_X;
+         n->InstLocation = prog->NumInstructions - 1;
          return inst;
       }
    case IR_ELSE:
       {
          struct prog_instruction *inst;
+         n->InstLocation = prog->NumInstructions;
          inst = new_instruction(prog, OPCODE_ELSE);
+         /* point IF's BranchTarget just after this instruction */
+         assert(n->BranchNode);
+         assert(n->BranchNode->InstLocation >= 0);
+         prog->Instructions[n->BranchNode->InstLocation].BranchTarget = prog->NumInstructions;
          return inst;
       }
    case IR_ENDIF:
       {
          struct prog_instruction *inst;
+         n->InstLocation = prog->NumInstructions;
          inst = new_instruction(prog, OPCODE_ENDIF);
+         /* point ELSE's BranchTarget to just after this inst */
+         assert(n->BranchNode);
+         assert(n->BranchNode->InstLocation >= 0);
+         prog->Instructions[n->BranchNode->InstLocation].BranchTarget = prog->NumInstructions;
          return inst;
       }
 
index 287dd9b1dbe5238b62e249177ec04c6e5de90e3e..fbd25c0fbfe99d592f6a191885eac5f5e1270c35 100644 (file)
@@ -897,62 +897,17 @@ execute_program( GLcontext *ctx,
                   /* do if-clause (just continue execution) */
                }
                else {
-                  /* search for else-clause or endif */
-                  /* XXX could encode location of the else/endif statement
-                   * in the IF instruction to avoid searching...
-                   */
-                  GLint ifDepth = 1;
-                  do {
-                     pc++;
-                     inst = program->Base.Instructions + pc;
-                     if (inst->Opcode == OPCODE_END) {
-                        /* mal-formed program! */
-                        _mesa_problem(ctx, "END found before ELSE/ENDIF");
-                        return GL_FALSE;
-                     }
-                     else if (inst->Opcode == OPCODE_IF) {
-                        /* nested if */
-                        ifDepth++;
-                     }
-                     else if (inst->Opcode == OPCODE_ELSE) {
-                        if (ifDepth == 1) {
-                           /* ok, continue normal execution */
-                           break;
-                        }
-                     }
-                     else if (inst->Opcode == OPCODE_ENDIF) {
-                        ifDepth--;
-                        if (ifDepth == 0) {
-                           /* ok, continue normal execution */
-                           break;
-                        }
-                     }
-                     assert(ifDepth >= 0);
-                  } while (pc < maxInst);
+                  /* go to the instruction after ELSE or ENDIF */
+                  assert(inst->BranchTarget >= 0);
+                  pc = inst->BranchTarget - 1;
                }
             }
             break;
          case OPCODE_ELSE:
             {
-               /* find/goto ENDIF */
-               GLint ifDepth = 1;
-               do {
-                  pc++;
-                  inst = program->Base.Instructions + pc;
-                  if (inst->Opcode == OPCODE_END) {
-                     /* mal-formed program! */
-                     abort();
-                  }
-                  else if (inst->Opcode == OPCODE_IF) {
-                     ifDepth++;
-                  }
-                  else if (inst->Opcode == OPCODE_ENDIF) {
-                     ifDepth--;
-                     if (ifDepth == 0)
-                        break;
-                  }
-                  assert(ifDepth >= 0);
-               } while (pc < maxInst);
+               /* goto ENDIF */
+               assert(inst->BranchTarget >= 0);
+               pc = inst->BranchTarget - 1;
             }
             break;
          case OPCODE_ENDIF: