mesa: Branch 'glsl-compiler-1' - 5 commits

Brian Paul brianp at kemper.freedesktop.org
Thu Feb 8 05:28:38 UTC 2007


 src/mesa/shader/prog_print.c           |    2 
 src/mesa/shader/slang/slang_codegen.c  |  256 ++++++---------------------------
 src/mesa/shader/slang/slang_emit.c     |  179 ++++++++++++++---------
 src/mesa/shader/slang/slang_ir.h       |    7 
 src/mesa/shader/slang/slang_link.c     |    2 
 src/mesa/shader/slang/slang_typeinfo.h |    2 
 src/mesa/swrast/s_fragprog.c           |   12 -
 7 files changed, 179 insertions(+), 281 deletions(-)

New commits:
diff-tree 2c75ef62ea8dfd690aab6fa4f2c85afba569a21f (from b35b4566c2d3bbf21c8fd955912f4c3c671f2bb9)
Author: Brian <brian at nostromo.localnet.net>
Date:   Wed Feb 7 16:19:19 2007 -0700

    remove old loop break/cont stuff

diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 61b5df5..bd7b30c 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -2295,25 +2295,15 @@ _slang_gen_operation(slang_assemble_ctx 
    case slang_oper_while:
       return _slang_gen_while(A, oper);
    case slang_oper_break:
-      if (!A->CurLoop && !A->CurLoopBreak) {
+      if (!A->CurLoop) {
          RETURN_ERROR("'break' not in loop", 0);
       }
-      if (UseHighLevelInstructions) {
-         return new_break(A->CurLoop);
-      }
-      else {
-         return new_jump(A->CurLoopBreak);
-      }
+      return new_break(A->CurLoop);
    case slang_oper_continue:
-      if (!A->CurLoop && !A->CurLoopCont) {
+      if (!A->CurLoop) {
          RETURN_ERROR("'continue' not in loop", 0);
       }
-      if (UseHighLevelInstructions) {
-         return new_cont(A->CurLoop);
-      }
-      else {
-         return new_jump(A->CurLoopCont);
-      }
+      return new_cont(A->CurLoop);
    case slang_oper_discard:
       return new_node0(IR_KILL);
 
diff --git a/src/mesa/shader/slang/slang_typeinfo.h b/src/mesa/shader/slang/slang_typeinfo.h
index d23bb6b..0f72fad 100644
--- a/src/mesa/shader/slang/slang_typeinfo.h
+++ b/src/mesa/shader/slang/slang_typeinfo.h
@@ -61,8 +61,6 @@ typedef struct slang_assemble_ctx_
    struct gl_program *program;
    slang_var_table *vartable;
    struct slang_function_ *CurFunction;
-   slang_atom CurLoopBreak;
-   slang_atom CurLoopCont;
    struct slang_ir_node_ *CurLoop;
 } slang_assemble_ctx;
 
diff-tree b35b4566c2d3bbf21c8fd955912f4c3c671f2bb9 (from c5e6bf63e6f8256c9e10bbbe8fb7a38de9d22921)
Author: Brian <brian at nostromo.localnet.net>
Date:   Wed Feb 7 16:11:00 2007 -0700

    high vs. low level if/then/else code emit

diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 2958837..6e2394f 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -43,7 +43,7 @@
 #define ANNOTATE 1
 
 
-static GLboolean EmitHighLevelInstructions = GL_FALSE;
+static GLboolean EmitHighLevelInstructions = GL_TRUE;
 
 
 /**
@@ -523,9 +523,9 @@ storage_annotation(const slang_ir_node *
       if (st->Index >= 0) {
          const GLfloat *val = prog->Parameters->ParameterValues[st->Index];
          if (st->Swizzle == SWIZZLE_NOOP)
-            sprintf(s, "{%f, %f, %f, %f}", val[0], val[1], val[2], val[3]);
+            sprintf(s, "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);
          else {
-            sprintf(s, "%f", val[GET_SWZ(st->Swizzle, 0)]);
+            sprintf(s, "%g", val[GET_SWZ(st->Swizzle, 0)]);
          }
       }
       break;
@@ -1059,28 +1059,50 @@ emit_if(slang_var_table *vt, slang_ir_no
 
    emit(vt, n->Children[0], prog);  /* the condition */
    ifInstLoc = prog->NumInstructions;
-   ifInst = new_instruction(prog, OPCODE_IF);
-   ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
-   ifInst->DstReg.CondSwizzle = SWIZZLE_X;
+   if (EmitHighLevelInstructions) {
+      ifInst = new_instruction(prog, OPCODE_IF);
+      ifInst->DstReg.CondMask = COND_NE;  /* if cond is non-zero */
+      ifInst->DstReg.CondSwizzle = SWIZZLE_X;
+   }
+   else {
+      /* conditional jump to else, or endif */
+      ifInst = new_instruction(prog, OPCODE_BRA);
+      ifInst->DstReg.CondMask = COND_EQ;  /* BRA if cond is zero */
+      ifInst->DstReg.CondSwizzle = SWIZZLE_X;
+      ifInst->Comment = _mesa_strdup("if zero");
+   }
 
    /* if body */
    emit(vt, n->Children[1], prog);
 
    if (n->Children[2]) {
-      /* else body */
+      /* have else body */
       elseInstLoc = prog->NumInstructions;
-      (void) new_instruction(prog, OPCODE_ELSE);
+      if (EmitHighLevelInstructions) {
+         (void) new_instruction(prog, OPCODE_ELSE);
+      }
+      else {
+         /* jump to endif instruction */
+         struct prog_instruction *inst;
+         inst = new_instruction(prog, OPCODE_BRA);
+         inst->Comment = _mesa_strdup("else");
+         inst->DstReg.CondMask = COND_TR;  /* always branch */
+      }
       ifInst = prog->Instructions + ifInstLoc;
       ifInst->BranchTarget = prog->NumInstructions;
 
       emit(vt, n->Children[2], prog);
    }
    else {
+      /* no else body */
       ifInst = prog->Instructions + ifInstLoc;
       ifInst->BranchTarget = prog->NumInstructions + 1;
    }
 
-   (void) new_instruction(prog, OPCODE_ENDIF);
+   if (EmitHighLevelInstructions) {
+      (void) new_instruction(prog, OPCODE_ENDIF);
+   }
+
    if (n->Children[2]) {
       struct prog_instruction *elseInst;
       elseInst = prog->Instructions + elseInstLoc;
@@ -1090,6 +1112,85 @@ emit_if(slang_var_table *vt, slang_ir_no
 }
 
 
+static struct prog_instruction *
+emit_loop(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
+{
+   struct prog_instruction *beginInst, *endInst;
+   GLuint beginInstLoc, endInstLoc;
+   slang_ir_node *ir;
+
+   /* emit OPCODE_BGNLOOP */
+   beginInstLoc = prog->NumInstructions;
+   if (EmitHighLevelInstructions) {
+      (void) new_instruction(prog, OPCODE_BGNLOOP);
+   }
+
+   /* body */
+   emit(vt, n->Children[0], prog);
+
+   endInstLoc = prog->NumInstructions;
+   if (EmitHighLevelInstructions) {
+      /* emit OPCODE_ENDLOOP */
+      endInst = new_instruction(prog, OPCODE_ENDLOOP);
+   }
+   else {
+      /* emit unconditional BRA-nch */
+      endInst = new_instruction(prog, OPCODE_BRA);
+      endInst->DstReg.CondMask = COND_TR;  /* always true */
+   }
+   /* end instruction's BranchTarget points to top of loop */
+   endInst->BranchTarget = beginInstLoc;
+
+   if (EmitHighLevelInstructions) {
+      /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
+      beginInst = prog->Instructions + beginInstLoc;
+      beginInst->BranchTarget = prog->NumInstructions - 1;
+   }
+
+   /* Done emitting loop code.  Now walk over the loop's linked list
+    * of BREAK and CONT nodes, filling in their BranchTarget fields
+    * (which will point to the ENDLOOP or ENDLOOP+1 instructions).
+    */
+   for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
+      struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
+      if (ir->Opcode == IR_BREAK) {
+         assert(inst->Opcode == OPCODE_BRK ||
+                inst->Opcode == OPCODE_BRA);
+         inst->BranchTarget = endInstLoc + 1;
+      }
+      else {
+         assert(ir->Opcode == IR_CONT);
+         assert(inst->Opcode == OPCODE_CONT ||
+                inst->Opcode == OPCODE_BRA);
+         /* XXX goto top of loop instead! */
+         inst->BranchTarget = endInstLoc;
+      }
+   }
+   return NULL;
+}
+
+
+/**
+ * Emit code for IR_CONT or IR_BREAK.
+ */
+static struct prog_instruction *
+emit_cont_break(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
+{
+   gl_inst_opcode opcode;
+   struct prog_instruction *inst;
+   n->InstLocation = prog->NumInstructions;
+   if (EmitHighLevelInstructions) {
+      opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
+   }
+   else {
+      opcode = OPCODE_BRA;
+   }
+   inst = new_instruction(prog, opcode);
+   inst->DstReg.CondMask = COND_TR;  /* always true */
+   return inst;
+}
+
+
 /**
  * Remove any SWIZZLE_NIL terms from given swizzle mask (smear prev term).
  * Ex: fix_swizzle("zyNN") -> "zyyy"
@@ -1305,77 +1406,11 @@ emit(slang_var_table *vt, slang_ir_node 
       return emit_if(vt, n, prog);
 
    case IR_LOOP:
-      {
-         struct prog_instruction *beginInst, *endInst;
-         GLuint beginInstLoc, endInstLoc;
-         slang_ir_node *ir;
-
-         /* emit OPCODE_BGNLOOP */
-         beginInstLoc = prog->NumInstructions;
-         if (EmitHighLevelInstructions) {
-            (void) new_instruction(prog, OPCODE_BGNLOOP);
-         }
-
-         /* body */
-         emit(vt, n->Children[0], prog);
-
-         endInstLoc = prog->NumInstructions;
-         if (EmitHighLevelInstructions) {
-            /* emit OPCODE_ENDLOOP */
-            endInst = new_instruction(prog, OPCODE_ENDLOOP);
-         }
-         else {
-            /* emit unconditional BRA-nch */
-            endInst = new_instruction(prog, OPCODE_BRA);
-            endInst->DstReg.CondMask = COND_TR;  /* always true */
-         }
-         /* end instruction's BranchTarget points to top of loop */
-         endInst->BranchTarget = beginInstLoc;
-
-         if (EmitHighLevelInstructions) {
-            /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
-            beginInst = prog->Instructions + beginInstLoc;
-            beginInst->BranchTarget = prog->NumInstructions - 1;
-         }
-
-         /* Done emitting loop code.  Now walk over the loop's linked list
-          * of BREAK and CONT nodes, filling in their BranchTarget fields
-          * (which will point to the ENDLOOP or ENDLOOP+1 instructions).
-          */
-         for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
-            struct prog_instruction *inst
-               = prog->Instructions + ir->InstLocation;
-            if (ir->Opcode == IR_BREAK) {
-               assert(inst->Opcode == OPCODE_BRK ||
-                      inst->Opcode == OPCODE_BRA);
-               inst->BranchTarget = endInstLoc + 1;
-            }
-            else {
-               assert(ir->Opcode == IR_CONT);
-               assert(inst->Opcode == OPCODE_CONT ||
-                      inst->Opcode == OPCODE_BRA);
-               inst->BranchTarget = endInstLoc;
-            }
-         }
-         return NULL;
-      }
+      return emit_loop(vt, n, prog);
    case IR_BREAK:
       /* fall-through */
    case IR_CONT:
-      {
-         gl_inst_opcode opcode;
-         struct prog_instruction *inst;
-         n->InstLocation = prog->NumInstructions;
-         if (EmitHighLevelInstructions) {
-            opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
-         }
-         else {
-            opcode = OPCODE_BRA;
-         }
-         inst = new_instruction(prog, opcode);
-         inst->DstReg.CondMask = COND_TR;  /* always true */
-         return inst;
-      }
+      return emit_cont_break(vt, n, prog);
 
    case IR_BEGIN_SUB:
       return new_instruction(prog, OPCODE_BGNSUB);
diff-tree c5e6bf63e6f8256c9e10bbbe8fb7a38de9d22921 (from a7c2c7d6b28570230fb1b4fbc47b94581ef7e6fa)
Author: Brian <brian at nostromo.localnet.net>
Date:   Wed Feb 7 16:09:13 2007 -0700

    s/%f/%g/

diff --git a/src/mesa/shader/prog_print.c b/src/mesa/shader/prog_print.c
index 6c303de..0adb589 100644
--- a/src/mesa/shader/prog_print.c
+++ b/src/mesa/shader/prog_print.c
@@ -429,7 +429,7 @@ _mesa_print_parameter_list(const struct 
    for (i = 0; i < list->NumParameters; i++){
       struct gl_program_parameter *param = list->Parameters + i;
       const GLfloat *v = list->ParameterValues[i];
-      _mesa_printf("param[%d] sz=%d %s %s = {%.3f, %.3f, %.3f, %.3f};\n",
+      _mesa_printf("param[%d] sz=%d %s %s = {%.3g, %.3g, %.3g, %.3g};\n",
                    i, param->Size,
                    program_file_string(list->Parameters[i].Type),
                    param->Name, v[0], v[1], v[2], v[3]);
diff-tree a7c2c7d6b28570230fb1b4fbc47b94581ef7e6fa (from 4aa487e7968d015af4fe729f697105448fcb843f)
Author: Brian <brian at nostromo.localnet.net>
Date:   Wed Feb 7 15:14:20 2007 -0700

    Remove old functions for generating BRA-based looping.

diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 14870f5..61b5df5 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -1373,60 +1373,10 @@ _slang_gen_function_call_name(slang_asse
 
 
 /**
- * Generate IR tree for a while-loop.  Use BRA-nch instruction.
- */
-static slang_ir_node *
-_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   /*
-    * label "__startWhile"
-    * eval expr (child[0]), updating condcodes
-    * branch if false to "__endWhile"
-    * body code
-    * jump "__startWhile"
-    * label "__endWhile"
-    */
-   slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startWhile");
-   slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endWhile");
-   slang_ir_node *startLab, *cond, *bra, *body, *jump, *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);
-   cond = _slang_gen_operation(A, &oper->children[0]);
-   cond = _slang_gen_cond(cond);
-   tree = new_seq(startLab, cond);
-
-   bra = new_cjump(endAtom, 0);
-   tree = new_seq(tree, bra);
-
-   body = _slang_gen_operation(A, &oper->children[1]);
-   if (body)
-      tree = new_seq(tree, body);
-
-   jump = new_jump(startAtom);
-   tree = new_seq(tree, jump);
-
-   endLab = new_label(endAtom);
-   tree = new_seq(tree, endLab);
-
-   /* Pop this loop */
-   A->CurLoopBreak = prevLoopBreak;
-   A->CurLoopCont = prevLoopCont;
-
-   return tree;
-}
-
-
-/**
  * Generate loop code using high-level IR_LOOP instruction
  */
 static slang_ir_node *
-_slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
 {
    slang_ir_node *prevLoop;
    /*
@@ -1464,56 +1414,10 @@ _slang_gen_hl_while(slang_assemble_ctx *
 
 
 /**
- * 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 do-while loop using high-level LOOP, IF instructions.
  */
 static slang_ir_node *
-_slang_gen_hl_do(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
 {
    slang_ir_node *prevLoop;
    /*
@@ -1550,73 +1454,10 @@ _slang_gen_hl_do(slang_assemble_ctx * A,
 
 
 /**
- * Generate IR tree for a for-loop.
- */
-static slang_ir_node *
-_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
-{
-   /*
-    * init code (child[0])
-    * label "__startFor"
-    * eval expr (child[1]), updating condcodes
-    * branch if false to "__endFor"
-    * code body (child[3])
-    * label "__continueFor"
-    * incr code (child[2])
-    * jump "__startFor"
-    * label "__endFor"
-    */
-   slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startFor");
-   slang_atom contAtom = slang_atom_pool_gen(A->atoms, "__continueFor");
-   slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endFor");
-   slang_ir_node *init, *startLab, *cond, *bra, *body, *contLab;
-   slang_ir_node *incr, *jump, *endLab, *tree;
-   slang_atom prevLoopBreak = A->CurLoopBreak;
-   slang_atom prevLoopCont = A->CurLoopCont;
-
-   /* Push this loop */
-   A->CurLoopBreak = endAtom;
-   A->CurLoopCont = contAtom;
-
-   init = _slang_gen_operation(A, &oper->children[0]);
-   startLab = new_label(startAtom);
-   tree = new_seq(init, startLab);
-
-   cond = _slang_gen_operation(A, &oper->children[1]);
-   cond = _slang_gen_cond(cond);
-   tree = new_seq(tree, cond);
-
-   bra = new_cjump(endAtom, 0);
-   tree = new_seq(tree, bra);
-
-   body = _slang_gen_operation(A, &oper->children[3]);
-   tree = new_seq(tree, body);
-
-   contLab = new_label(contAtom);
-   tree = new_seq(tree, contLab);
-
-   incr = _slang_gen_operation(A, &oper->children[2]);
-   tree = new_seq(tree, incr);
-
-   jump = new_jump(startAtom);
-   tree = new_seq(tree, jump);
-
-   endLab = new_label(endAtom);
-   tree = new_seq(tree, endLab);
-
-   /* Pop this loop */
-   A->CurLoopBreak = prevLoopBreak;
-   A->CurLoopCont = prevLoopCont;
-
-   return tree;
-}
-
-
-/**
  * Generate for-loop using high-level IR_LOOP instruction.
  */
 static slang_ir_node *
-_slang_gen_hl_for(slang_assemble_ctx * A, const slang_operation *oper)
+_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
 {
    slang_ir_node *prevLoop;
    /*
@@ -2447,21 +2288,12 @@ _slang_gen_operation(slang_assemble_ctx 
    case slang_oper_expression:
       return _slang_gen_operation(A, &oper->children[0]);
       break;
-   case slang_oper_while:
-      if (UseHighLevelInstructions)
-         return _slang_gen_hl_while(A, oper);
-      else
-         return _slang_gen_while(A, oper);
-   case slang_oper_do:
-      if (UseHighLevelInstructions)
-         return _slang_gen_hl_do(A, oper);
-      else
-         return _slang_gen_do(A, oper);
    case slang_oper_for:
-      if (UseHighLevelInstructions)
-         return _slang_gen_hl_for(A, oper);
-      else
-         return _slang_gen_for(A, oper);
+      return _slang_gen_for(A, oper);
+   case slang_oper_do:
+      return _slang_gen_do(A, oper);
+   case slang_oper_while:
+      return _slang_gen_while(A, oper);
    case slang_oper_break:
       if (!A->CurLoop && !A->CurLoopBreak) {
          RETURN_ERROR("'break' not in loop", 0);
diff-tree 4aa487e7968d015af4fe729f697105448fcb843f (from 1f99a7514e9c36b7ce2c6c1724a6584790656415)
Author: Brian <brian at nostromo.localnet.net>
Date:   Wed Feb 7 15:12:13 2007 -0700

    Use IR_LOOP to represent do-while and for-loops.
    
    Also, start moving high vs. low-level instruction selection into slang_emit.c

diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c
index 42c1f08..14870f5 100644
--- a/src/mesa/shader/slang/slang_codegen.c
+++ b/src/mesa/shader/slang/slang_codegen.c
@@ -1423,7 +1423,7 @@ _slang_gen_while(slang_assemble_ctx * A,
 
 
 /**
- * Generate IR tree for a while-loop using high-level LOOP, IF instructions.
+ * Generate loop code using high-level IR_LOOP instruction
  */
 static slang_ir_node *
 _slang_gen_hl_while(slang_assemble_ctx * A, const slang_operation *oper)
@@ -1510,6 +1510,46 @@ _slang_gen_do(slang_assemble_ctx * A, co
 
 
 /**
+ * Generate IR tree for a do-while loop using high-level LOOP, IF instructions.
+ */
+static slang_ir_node *
+_slang_gen_hl_do(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   slang_ir_node *prevLoop;
+   /*
+    * LOOP:
+    *    body code (child[0])
+    *    eval expr (child[1]), updating condcodes
+    *    IF !expr:
+    *       BRK
+    */
+   slang_ir_node *ifThen, *cond, *body, *loop;
+
+   loop = new_loop(NULL);
+
+   /* save old, push new loop */
+   prevLoop = A->CurLoop;
+   A->CurLoop = loop;
+
+   body = _slang_gen_operation(A, &oper->children[0]);
+
+   cond = _slang_gen_operation(A, &oper->children[1]);
+   cond = new_node1(IR_NOT, cond);
+   cond = _slang_gen_cond(cond);
+
+   ifThen = new_if(cond,
+                   new_break(A->CurLoop),
+                   NULL);
+
+   loop->Children[0] = new_seq(body, ifThen);
+
+   A->CurLoop = prevLoop; /* pop loop, restore prev */
+
+   return loop;
+}
+
+
+/**
  * Generate IR tree for a for-loop.
  */
 static slang_ir_node *
@@ -1573,69 +1613,48 @@ _slang_gen_for(slang_assemble_ctx * A, c
 
 
 /**
- * Generate IR tree for a for-loop, using high-level BGNLOOP/ENDLOOP and
- * IF/ENDIF instructions.
- *
- * XXX note done yet!
+ * Generate for-loop using high-level IR_LOOP instruction.
  */
 static slang_ir_node *
 _slang_gen_hl_for(slang_assemble_ctx * A, const slang_operation *oper)
 {
+   slang_ir_node *prevLoop;
    /*
-    * init code (child[0])
-    * BGNLOOP
+    * init (child[0])
+    * LOOP:
     *    eval expr (child[1]), updating condcodes
-    *    IF !expr THEN
+    *    IF !expr:
     *       BRK
-    *    ENDIF
-    *    code body (child[3])
-    *    label "__continueFor"   // jump here for "continue"
-    *    incr code (child[2])
-    * ENDLOOP
+    *    body code (child[3])
+    *    incr code (child[2])   // XXX continue here
     */
-   slang_atom startAtom = slang_atom_pool_gen(A->atoms, "__startFor");
-   slang_atom contAtom = slang_atom_pool_gen(A->atoms, "__continueFor");
-   slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__endFor");
-   slang_ir_node *init, *startLab, *cond, *bra, *body, *contLab;
-   slang_ir_node *incr, *jump, *endLab, *tree;
-   slang_atom prevLoopBreak = A->CurLoopBreak;
-   slang_atom prevLoopCont = A->CurLoopCont;
-
-   /* Push this loop */
-   A->CurLoopBreak = endAtom;
-   A->CurLoopCont = contAtom;
+   slang_ir_node *init, *ifThen, *cond, *body, *loop, *incr;
 
    init = _slang_gen_operation(A, &oper->children[0]);
-   startLab = new_label(startAtom);
-   tree = new_seq(init, startLab);
+   loop = new_loop(NULL);
+
+   /* save old, push new loop */
+   prevLoop = A->CurLoop;
+   A->CurLoop = loop;
 
    cond = _slang_gen_operation(A, &oper->children[1]);
+   cond = new_node1(IR_NOT, cond);
    cond = _slang_gen_cond(cond);
-   tree = new_seq(tree, cond);
 
-   bra = new_cjump(endAtom, 0);
-   tree = new_seq(tree, bra);
+   ifThen = new_if(cond,
+                   new_break(A->CurLoop),
+                   NULL);
 
    body = _slang_gen_operation(A, &oper->children[3]);
-   tree = new_seq(tree, body);
-
-   contLab = new_label(contAtom);
-   tree = new_seq(tree, contLab);
 
    incr = _slang_gen_operation(A, &oper->children[2]);
-   tree = new_seq(tree, incr);
-
-   jump = new_jump(startAtom);
-   tree = new_seq(tree, jump);
 
-   endLab = new_label(endAtom);
-   tree = new_seq(tree, endLab);
+   loop->Children[0] = new_seq(ifThen,
+                               new_seq(body,incr));
 
-   /* Pop this loop */
-   A->CurLoopBreak = prevLoopBreak;
-   A->CurLoopCont = prevLoopCont;
+   A->CurLoop = prevLoop; /* pop loop, restore prev */
 
-   return tree;
+   return new_seq(init, loop);
 }
 
 
@@ -2434,7 +2453,10 @@ _slang_gen_operation(slang_assemble_ctx 
       else
          return _slang_gen_while(A, oper);
    case slang_oper_do:
-      return _slang_gen_do(A, oper);
+      if (UseHighLevelInstructions)
+         return _slang_gen_hl_do(A, oper);
+      else
+         return _slang_gen_do(A, oper);
    case slang_oper_for:
       if (UseHighLevelInstructions)
          return _slang_gen_hl_for(A, oper);
diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c
index 2d5a7cf..2958837 100644
--- a/src/mesa/shader/slang/slang_emit.c
+++ b/src/mesa/shader/slang/slang_emit.c
@@ -43,6 +43,9 @@
 #define ANNOTATE 1
 
 
+static GLboolean EmitHighLevelInstructions = GL_FALSE;
+
+
 /**
  * Assembly and IR info
  */
@@ -1304,57 +1307,72 @@ emit(slang_var_table *vt, slang_ir_node 
    case IR_LOOP:
       {
          struct prog_instruction *beginInst, *endInst;
-         GLuint endInstLoc;
-         slang_ir_node *p;
+         GLuint beginInstLoc, endInstLoc;
+         slang_ir_node *ir;
 
-         /* save location of this instruction, used by OPCODE_ENDLOOP */
-         n->InstLocation = prog->NumInstructions;
-         (void) new_instruction(prog, OPCODE_BGNLOOP);
+         /* emit OPCODE_BGNLOOP */
+         beginInstLoc = prog->NumInstructions;
+         if (EmitHighLevelInstructions) {
+            (void) new_instruction(prog, OPCODE_BGNLOOP);
+         }
 
          /* body */
          emit(vt, n->Children[0], prog);
 
          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;
+         if (EmitHighLevelInstructions) {
+            /* emit OPCODE_ENDLOOP */
+            endInst = new_instruction(prog, OPCODE_ENDLOOP);
+         }
+         else {
+            /* emit unconditional BRA-nch */
+            endInst = new_instruction(prog, OPCODE_BRA);
+            endInst->DstReg.CondMask = COND_TR;  /* always true */
+         }
+         /* end instruction's BranchTarget points to top of loop */
+         endInst->BranchTarget = beginInstLoc;
+
+         if (EmitHighLevelInstructions) {
+            /* BGNLOOP's BranchTarget points to the ENDLOOP inst */
+            beginInst = prog->Instructions + beginInstLoc;
+            beginInst->BranchTarget = prog->NumInstructions - 1;
+         }
 
          /* Done emitting loop code.  Now walk over the loop's linked list
-          * of BREAK and CONT nodes, filling in their BranchTarget fields.
+          * of BREAK and CONT nodes, filling in their BranchTarget fields
+          * (which will point to the ENDLOOP or ENDLOOP+1 instructions).
           */
-         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;
+         for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
+            struct prog_instruction *inst
+               = prog->Instructions + ir->InstLocation;
+            if (ir->Opcode == IR_BREAK) {
+               assert(inst->Opcode == OPCODE_BRK ||
+                      inst->Opcode == OPCODE_BRA);
+               inst->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;
+               assert(ir->Opcode == IR_CONT);
+               assert(inst->Opcode == OPCODE_CONT ||
+                      inst->Opcode == OPCODE_BRA);
+               inst->BranchTarget = endInstLoc;
             }
          }
          return NULL;
       }
-   case IR_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:
+      /* fall-through */
+   case IR_CONT:
       {
+         gl_inst_opcode opcode;
          struct prog_instruction *inst;
          n->InstLocation = prog->NumInstructions;
-         inst = new_instruction(prog, OPCODE_BRK);
+         if (EmitHighLevelInstructions) {
+            opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
+         }
+         else {
+            opcode = OPCODE_BRA;
+         }
+         inst = new_instruction(prog, opcode);
          inst->DstReg.CondMask = COND_TR;  /* always true */
          return inst;
       }
diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h
index a7c858c..0c827d9 100644
--- a/src/mesa/shader/slang/slang_ir.h
+++ b/src/mesa/shader/slang/slang_ir.h
@@ -39,7 +39,7 @@
 
 
 /**
- * Intermediate Representation opcode
+ * Intermediate Representation opcodes
  */
 typedef enum
 {
@@ -64,6 +64,11 @@ typedef enum
    IR_CONT,      /* continue loop */
    IR_BREAK,     /* break loop */
 
+   IR_BREAK_IF_TRUE,
+   IR_BREAK_IF_FALSE,
+   IR_CONT_IF_TRUE,
+   IR_CONT_IF_FALSE,
+
    IR_MOVE,
    IR_ADD,
    IR_SUB,
diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c
index 017cf60..b1d355f 100644
--- a/src/mesa/shader/slang/slang_link.c
+++ b/src/mesa/shader/slang/slang_link.c
@@ -298,7 +298,7 @@ _slang_resolve_branches(struct gl_progra
 
    for (i = 0; i < prog->NumInstructions; i++) {
       struct prog_instruction *inst = prog->Instructions + i;
-      if (inst->Opcode == OPCODE_BRA) {
+      if (inst->Opcode == OPCODE_BRA && inst->BranchTarget < 0) {
          for (j = 0; j < numTargets; j++) {
             if (!strcmp(inst->Comment, targets[j].Name)) {
                inst->BranchTarget = targets[j].Pos;
diff --git a/src/mesa/swrast/s_fragprog.c b/src/mesa/swrast/s_fragprog.c
index 403a03a..ace10a9 100644
--- a/src/mesa/swrast/s_fragprog.c
+++ b/src/mesa/swrast/s_fragprog.c
@@ -675,9 +675,10 @@ execute_program( GLcontext *ctx,
                }
             }
             break;
-         case OPCODE_BGNLOOP: /* begin loop */
+         case OPCODE_BGNLOOP:
+            /* no-op */
             break;
-         case OPCODE_ENDLOOP: /* end loop */
+         case OPCODE_ENDLOOP:
             /* subtract 1 here since pc is incremented by for(pc) loop */
             pc = inst->BranchTarget - 1; /* go to matching BNGLOOP */
             break;
@@ -695,10 +696,7 @@ execute_program( GLcontext *ctx,
                    test_cc(machine->CondCodes[GET_SWZ(swizzle, 2)], condMask) ||
                    test_cc(machine->CondCodes[GET_SWZ(swizzle, 3)], condMask)) {
                   /* take branch */
-                  pc = inst->BranchTarget;
-                  /*
-                  printf("Take branch to %u\n", pc);
-                  */
+                  pc = inst->BranchTarget - 1;
                }
             }
             break;
@@ -721,7 +719,7 @@ execute_program( GLcontext *ctx,
                      return GL_TRUE; /* Per GL_NV_vertex_program2 spec */
                   }
                   machine->CallStack[machine->StackDepth++] = pc + 1;
-                  pc = inst->BranchTarget;
+                  pc = inst->BranchTarget; /* XXX - 1 ??? */
                }
             }
             break;



More information about the mesa-commit mailing list