New IR_COND node for evaluating conditional expressions (for if/while/for).
authorBrian <brian@yutani.localnet.net>
Wed, 20 Dec 2006 19:41:59 +0000 (12:41 -0700)
committerBrian <brian@yutani.localnet.net>
Wed, 20 Dec 2006 19:41:59 +0000 (12:41 -0700)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_ir.h

index 51bf26a..a2be043 100644 (file)
@@ -813,6 +813,14 @@ _slang_is_noop(const slang_operation *oper)
 }
 
 
+static slang_ir_node *
+_slang_gen_cond(slang_ir_node *n)
+{
+   slang_ir_node *c = new_node(IR_COND, n, NULL);
+   return c;
+}
+
+
 /**
  * Assemble a function call, given a particular function name.
  * \param name  the function's name (operators like '*' are possible).
@@ -866,6 +874,7 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
 
    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);
@@ -922,6 +931,7 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
    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);
@@ -972,6 +982,7 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
    slang_atom endifAtom = slang_atom_pool_gen(A->atoms, "__endif");
 
    cond = _slang_gen_operation(A, &oper->children[0]);
+   cond = _slang_gen_cond(cond);
    /*assert(cond->Store);*/
    bra = new_cjump(haveElseClause ? elseAtom : endifAtom);
    tree = new_seq(cond, bra);
index ba1290b..d7c2245 100644 (file)
@@ -85,6 +85,7 @@ static slang_ir_info IrInfo[] = {
    { IR_LABEL, "IR_LABEL", 0, 0, 0 },
    { IR_JUMP, "IR_JUMP", 0, 0, 0 },
    { IR_CJUMP, "IR_CJUMP", 0, 0, 0 },
+   { IR_COND, "IR_COND", 0, 0, 0 },
    { IR_CALL, "IR_CALL", 0, 0, 0 },
    { IR_MOVE, "IR_MOVE", 0, 0, 1 },
    { IR_NOT, "IR_NOT", 0, 1, 1 },
@@ -300,6 +301,10 @@ slang_print_ir(const slang_ir_node *n, int indent)
    case IR_LABEL:
       printf("LABEL: %s\n", n->Target);
       break;
+   case IR_COND:
+      printf("COND\n");
+      slang_print_ir(n->Children[0], indent + 3);
+      break;
    case IR_JUMP:
       printf("JUMP %s\n", n->Target);
       break;
@@ -897,12 +902,6 @@ 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;
 }
 
@@ -1075,7 +1074,6 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
    case IR_EXP:
    case IR_EXP2:
       return emit_binop(gc, n, prog);
-      break;
    case IR_RSQ:
    case IR_RCP:
    case IR_FLOOR:
@@ -1084,12 +1082,40 @@ emit(slang_gen_context *gc, slang_ir_node *n, struct gl_program *prog)
    case IR_SIN:
    case IR_COS:
       return emit_unop(gc, n, prog);
-      break;
    case IR_LABEL:
       return emit_label(n->Target, prog);
    case IR_FLOAT:
       n->Store = alloc_constant(n->Value, 4, prog); /*XXX fix size */
       break;
+   case IR_COND:
+      {
+         /* Conditional expression (in if/while/for stmts).
+          * Need to update condition code register.
+          * Next instruction is typically an IR_CJUMP.
+          */
+         /* last child expr instruction: */
+         struct prog_instruction *inst = emit(gc, n->Children[0], prog);
+         if (inst) {
+            /* set inst's CondUpdate flag */
+            inst->CondUpdate = GL_TRUE;
+            return inst; /* XXX or null? */
+         }
+         else {
+            /* This'll happen for things like "if (i) ..." where no code
+             * is normally generated for the expression "i".
+             * Generate a move instruction just to set condition codes.
+             */
+            slang_alloc_temp_storage(gc, n, 1);
+            inst = new_instruction(prog, OPCODE_MOV);
+            inst->CondUpdate = GL_TRUE;
+            storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
+            storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store,
+                               n->Children[0]->Swizzle);
+            free_temporary(gc, n->Store->Index, n->Store->Size);
+            return inst; /* XXX or null? */
+         }
+      }
+      return NULL;
    case IR_JUMP:
       return emit_jump(n->Target, prog);
    case IR_CJUMP:
index 5c054a5..188d7d9 100644 (file)
 typedef enum
 {
    IR_NOP = 0,
-   IR_SEQ,
+   IR_SEQ,     /* sequence (eval left, then right) */
    IR_LABEL,   /* target of a jump or cjump */
    IR_JUMP,    /* unconditional jump */
    IR_CJUMP,   /* conditional jump */
-   IR_CALL,
+   IR_COND,    /* conditional expression */
+   IR_CALL,    /* call subroutine */
    IR_MOVE,
    IR_ADD,
    IR_SUB,
@@ -56,27 +57,27 @@ typedef enum
    IR_DIV,
    IR_DOT4,
    IR_DOT3,
-   IR_CROSS,
+   IR_CROSS,   /* vec3 cross product */
    IR_MIN,
    IR_MAX,
-   IR_SEQUAL,
-   IR_SNEQUAL,
-   IR_SGE,
-   IR_SGT,
-   IR_POW,
-   IR_EXP,
-   IR_EXP2,
-   IR_LOG2,
-   IR_RSQ,
-   IR_RCP,
+   IR_SEQUAL,  /* Set if not equal */
+   IR_SNEQUAL, /* Set if equal */
+   IR_SGE,     /* Set if greater or equal */
+   IR_SGT,     /* Set if greater than */
+   IR_POW,     /* x^y */
+   IR_EXP,     /* e^x */
+   IR_EXP2,    /* 2^x */
+   IR_LOG2,    /* log base 2 */
+   IR_RSQ,     /* 1/sqrt() */
+   IR_RCP,     /* recipricol */
    IR_FLOOR,
    IR_FRAC,
    IR_ABS,
-   IR_SIN,
-   IR_COS,
-   IR_NOT,
-   IR_VAR,
-   IR_VAR_DECL,
+   IR_SIN,     /* sine */
+   IR_COS,     /* cosine */
+   IR_NOT,     /* logical not */
+   IR_VAR,     /* variable reference */
+   IR_VAR_DECL,/* var declaration */
    IR_FLOAT,
    IR_FIELD,
    IR_I_TO_F