Implement if-conditionals and while loops, added temporary resolve-branches function...
authorBrian <brian@yutani.localnet.net>
Mon, 18 Dec 2006 17:05:24 +0000 (10:05 -0700)
committerBrian <brian@yutani.localnet.net>
Mon, 18 Dec 2006 17:05:24 +0000 (10:05 -0700)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_link2.c

index 2f2b2b2a4e069a1f0557f22e295fcc50efca80e5..9cfcfd45d3089675deba214f009fcb3b86e37f49 100644 (file)
@@ -122,10 +122,10 @@ new_seq(slang_ir_node *left, slang_ir_node *right)
 }
 
 static slang_ir_node *
-new_label(const char *name)
+new_label(slang_atom labName)
 {
    slang_ir_node *n = new_node(IR_LABEL, NULL, NULL);
-   n->Target = _mesa_strdup(name);
+   n->Target = (char *) labName; /*_mesa_strdup(name);*/
    return n;
 }
 
@@ -141,20 +141,20 @@ new_float_literal(float x, float y, float z, float w)
 }
 
 static slang_ir_node *
-new_cjump(slang_ir_node *cond, const char *target)
+new_cjump(slang_atom target)
 {
-   slang_ir_node *n = new_node(IR_CJUMP, cond, NULL);
-   n->Target = _mesa_strdup(target);
+   slang_ir_node *n = new_node(IR_CJUMP, NULL, NULL);
+   if (n)
+      n->Target = (char *) target;
    return n;
 }
 
 static slang_ir_node *
-new_jump(const char *target)
+new_jump(slang_atom target)
 {
    slang_ir_node *n = new_node(IR_JUMP, NULL, NULL);
-   if (n) {
-      n->Target = _mesa_strdup(target);
-   }
+   if (n)
+      n->Target = (char *) target;
    return n;
 }
 
@@ -893,6 +893,16 @@ slang_assemble_asm(slang_assemble_ctx *A, slang_operation *oper,
 
 
 
+static GLboolean
+_slang_is_noop(const slang_operation *oper)
+{
+   if (!oper ||
+       oper->type == slang_oper_void ||
+       (oper->num_children == 1 && oper->children[0].type == slang_oper_void))
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
 
 
 /**
@@ -922,6 +932,88 @@ slang_assemble_function_call_name(slang_assemble_ctx *A, const char *name,
 }
 
 
+static slang_ir_node *
+_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
+{
+   /*
+    * label "__whileStart"
+    * eval expr (child[0]), updating condcodes
+    * branch if false to "__endWhile"
+    * code body
+    * jump "__whileStart"
+    * 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;
+
+   startLab = new_label(startAtom);
+   cond = slang_assemble_operation(A, &oper->children[0]);
+   tree = new_seq(startLab, cond);
+
+   bra = new_cjump(endAtom);
+   tree = new_seq(tree, bra);
+
+   body = slang_assemble_operation(A, &oper->children[1]);
+   tree = new_seq(tree, body);
+
+   jump = new_jump(startAtom);
+   tree = new_seq(tree, jump);
+
+   endLab = new_label(endAtom);
+   tree = new_seq(tree, endLab);
+
+   return tree;
+}
+
+
+static slang_ir_node *
+_slang_gen_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"
+    */
+   const GLboolean haveElseClause = !_slang_is_noop(&oper->children[2]);
+   slang_ir_node *cond, *bra, *trueBody, *endifLab, *tree;
+   slang_atom elseAtom = slang_atom_pool_gen(A->atoms, "__else");
+   slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif");
+
+   cond = slang_assemble_operation(A, &oper->children[0]);
+   /*assert(cond->Store);*/
+   bra = new_cjump(haveElseClause ? elseAtom : endifAtom);
+   tree = new_seq(cond, bra);
+
+   trueBody = slang_assemble_operation(A, &oper->children[1]);
+   tree = new_seq(tree, trueBody);
+
+   if (haveElseClause) {
+      /* else clause */
+      slang_ir_node *jump, *elseLab, *falseBody;
+      jump = new_jump(endifAtom);
+      tree = new_seq(tree, jump);
+
+      elseLab = new_label(elseAtom);
+      tree = new_seq(tree, elseLab);
+
+      falseBody = slang_assemble_operation(A, &oper->children[2]);
+      tree = new_seq(tree, falseBody);
+   }
+
+   endifLab = new_label(endifAtom);
+   tree = new_seq(tree, endifLab);
+
+   return tree;
+}
+
+
+
 static slang_ir_node *
 slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
 {
@@ -944,25 +1036,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
       return slang_assemble_operation(A, &oper->children[0]);
       break;
    case slang_oper_while:
-      {
-         slang_ir_node *tree;
-         slang_ir_node *nStartLabel = new_label("while-start");
-         slang_ir_node *nCond = slang_assemble_operation(A, &oper->children[0]);
-         slang_ir_node *nNotCond = new_node(IR_NOT, nCond, NULL);
-         slang_ir_node *nBody = slang_assemble_operation(A, &oper->children[1]);
-         slang_ir_node *nEndLabel = new_label("while-end");
-         slang_ir_node *nCJump = new_cjump(nNotCond, "while-end");
-         slang_ir_node *nJump = new_jump("while-start");
-
-         tree = new_seq(nStartLabel, nCond);
-         tree = new_seq(tree, nNotCond);
-         tree = new_seq(tree, nBody);
-         tree = new_seq(tree, nEndLabel);
-         tree = new_seq(tree, nCJump);
-         tree = new_seq(tree, nJump);
-         return tree;
-      }
-      break;
+      return _slang_gen_while(A, oper);
    case slang_oper_equal:
       return new_node(IR_SEQUAL,
                       slang_assemble_operation(A, &oper->children[0]),
@@ -1145,24 +1219,7 @@ slang_assemble_operation(slang_assemble_ctx * A, slang_operation *oper)
       }
       break;
    case slang_oper_if:
-      {
-         slang_ir_node *cond, *bra, *body, *endif, *tree;
-
-         cond = slang_assemble_operation(A, &oper->children[0]);
-         /*assert(cond->Store);*/
-         bra = new_node(IR_CJUMP, NULL, NULL);
-         bra->Target = _mesa_strdup("__endif");
-
-         body = slang_assemble_operation(A, &oper->children[1]);
-
-         endif = new_label("__endif");
-
-         tree = new_seq(cond, bra);
-         tree = new_seq(tree, body);
-         tree = new_seq(tree, endif);
-         return tree;
-      }
-      break;
+      return _slang_gen_if(A, oper);
    case slang_oper_field:
       {
          slang_assembly_typeinfo ti;
index fbee314d242f506303e7f77d656ec8c8e2a574ec..ba1290b45e4db846a0e0229482a4532a06c28332 100644 (file)
@@ -897,6 +897,12 @@ emit_binop(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
    storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store,
                       n->Children[1]->Swizzle);
    inst->Comment = n->Comment;
+
+   if (inst->Opcode == OPCODE_SGT) {
+      /* update cond codes */
+      inst->CondUpdate = GL_TRUE;
+   }
+
    return inst;
 }
 
@@ -951,6 +957,18 @@ emit_cjump(const char *target, struct gl_program *prog)
 }
 
 
+static struct prog_instruction *
+emit_jump(const char *target, struct gl_program *prog)
+{
+   struct prog_instruction *inst;
+   inst = new_instruction(prog, OPCODE_BRA);
+   inst->DstReg.CondMask = COND_TR;  /* always branch */
+   /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/
+   inst->Comment = _mesa_strdup(target);
+   return inst;
+}
+
+
 
 static struct prog_instruction *
 emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
@@ -1069,15 +1087,11 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
       break;
    case IR_LABEL:
       return emit_label(n->Target, prog);
-   case IR_JUMP:
-#if 0
-      inst = new_instruction(prog, OPCODE_BRA);
-      inst->Comment = _mesa_strdup(n->Target);
-#endif
-      break;
    case IR_FLOAT:
       n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
       break;
+   case IR_JUMP:
+      return emit_jump(n->Target, prog);
    case IR_CJUMP:
       return emit_cjump(n->Target, prog);
    default:
index 6a276d69ac06002ba957132120332bd0a1cc6386..c170b3e053f4c66e2178c558afb0eccb0362ba6f 100644 (file)
@@ -229,6 +229,47 @@ link_uniform_vars(struct gl_linked_program *linked, struct gl_program *prog)
 }
 
 
+/**
+ * XXX Temporary
+ */
+static void
+slang_resolve_branches(struct gl_program *prog)
+{
+   struct target {
+      const char *Name;
+      GLuint Pos;
+   };
+   struct target targets[500];
+   GLuint numTargets = 0;
+   GLuint i, j;
+
+   for (i = 0; i < prog->NumInstructions; i++) {
+      struct prog_instruction *inst = prog->Instructions + i;
+      if (inst->Opcode == OPCODE_NOP && inst->Comment) {
+         targets[numTargets].Name = inst->Comment;
+         targets[numTargets].Pos = i;
+         numTargets++;
+      }
+   }
+
+   for (i = 0; i < prog->NumInstructions; i++) {
+      struct prog_instruction *inst = prog->Instructions + i;
+      if (inst->Opcode == OPCODE_BRA) {
+         for (j = 0; j < numTargets; j++) {
+            if (!strcmp(inst->Comment, targets[j].Name)) {
+               inst->BranchTarget = targets[j].Pos;
+               break;
+            }
+         }
+         if (j == numTargets) {
+            abort();
+         }
+      }
+   }
+}
+
+
+
 /**
  * Shader linker.  Currently:
  *
@@ -298,6 +339,9 @@ _slang_link2(GLcontext *ctx,
    linked->VertexProgram->Base.Parameters = linked->Uniforms;
    linked->FragmentProgram->Base.Parameters = linked->Uniforms;
 
+   slang_resolve_branches(&linked->VertexProgram->Base);
+   slang_resolve_branches(&linked->FragmentProgram->Base);
+
 #if 1
    printf("************** original fragment program\n");
    _mesa_print_program(&fragProg->Base);