Implement codegen for the selection operator ( b ? x : y )
authorBrian <brian@yutani.localnet.net>
Wed, 17 Jan 2007 00:38:39 +0000 (17:38 -0700)
committerBrian <brian@yutani.localnet.net>
Wed, 17 Jan 2007 00:38:39 +0000 (17:38 -0700)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c

index 4213e1c4b4f1a26cf9fdf93f3f93300cf943fd80..0189b751347e471192a2a8558bbf8f522e2377af 100644 (file)
@@ -1477,6 +1477,96 @@ _slang_gen_if(slang_assemble_ctx * A, const slang_operation *oper)
 }
 
 
+/**
+ * Generate IR node for storage of a temporary of given size.
+ */
+static slang_ir_node *
+_slang_gen_temporary(GLint size)
+{
+   slang_ir_storage *store;
+   slang_ir_node *n;
+
+   store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size);
+   if (store) {
+      n = new_node(IR_VAR_DECL, NULL, NULL);
+      if (n) {
+         n->Store = store;
+      }
+      else {
+         free(store);
+      }
+   }
+   return n;
+}
+
+
+/**
+ * Generate code for a selection expression:   b ? x : y
+ */
+static slang_ir_node *
+_slang_gen_select(slang_assemble_ctx *A, slang_operation *oper)
+{
+   slang_atom altAtom = slang_atom_pool_gen(A->atoms, "__selectAlt");
+   slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__selectEnd");
+   slang_ir_node *altLab, *endLab;
+   slang_ir_node *tree, *tmpDecl, *tmpVar, *cond, *cjump, *jump;
+   slang_ir_node *bodx, *body, *assignx, *assigny;
+    slang_assembly_typeinfo type;
+   int size;
+
+   /* size of x or y's type */
+   slang_assembly_typeinfo_construct(&type);
+   _slang_typeof_operation(A, &oper->children[1], &type);
+   size = _slang_sizeof_type_specifier(&type.spec);
+   assert(size > 0);
+
+   /* temporary var */
+   tmpDecl = _slang_gen_temporary(size);
+
+   /* eval condition */
+   cond = _slang_gen_operation(A, &oper->children[0]);
+   cond = _slang_gen_cond(cond);
+   tree = new_seq(tmpDecl, cond);
+
+   /* jump if true to "alt" label */
+   cjump = new_cjump(altAtom);
+   tree = new_seq(tree, cjump);
+
+   /* evaluate child 2 (y) and assign to tmp */
+   tmpVar = new_node(IR_VAR, NULL, NULL);
+   tmpVar->Store = tmpDecl->Store;
+   body = _slang_gen_operation(A, &oper->children[2]);
+   assigny = new_node(IR_MOVE, tmpVar, body);
+   tree = new_seq(tree, assigny);
+
+   /* jump to "end" label */
+   jump = new_jump(endAtom);
+   tree = new_seq(tree, jump);
+
+   /* "alt" label */
+   altLab = new_label(altAtom);
+   tree = new_seq(tree, altLab);
+
+   /* evaluate child 1 (x) and assign to tmp */
+   tmpVar = new_node(IR_VAR, NULL, NULL);
+   tmpVar->Store = tmpDecl->Store;
+   bodx = _slang_gen_operation(A, &oper->children[1]);
+   assignx = new_node(IR_MOVE, tmpVar, bodx);
+   tree = new_seq(tree, assignx);
+
+   /* "end" label */
+   endLab = new_label(endAtom);
+   tree = new_seq(tree, endLab);
+   
+   /* tmp var value */
+   tmpVar = new_node(IR_VAR, NULL, NULL);
+   tmpVar->Store = tmpDecl->Store;
+   tree = new_seq(tree, tmpVar);
+
+   return tree;
+}
+
+
 /**
  * Generate IR tree for a return statement.
  */
@@ -1643,24 +1733,6 @@ _slang_gen_variable(slang_assemble_ctx * A, slang_operation *oper)
 }
 
 
-#if 0
-static slang_ir_node *
-_slang_gen_logical_and(slang_assemble_ctx * A, slang_operation *oper)
-{
-   /*
-    * bool b;
-    * b = test(child[0]);
-    * if !b goto endLab;
-    * b = test(child[1]);
-    * endLab:
-    * (b)
-    */
-   slang_ir_node *temp;
-
-}
-#endif
-
-
 /**
  * Generate IR tree for an assignment (=).
  */
@@ -1671,6 +1743,10 @@ _slang_gen_assignment(slang_assemble_ctx * A, slang_operation *oper)
        oper->children[1].type == slang_oper_call) {
       /* Special case of:  x = f(a, b)
        * Replace with f(a, b, x)  (where x == hidden __retVal out param)
+       *
+       * XXX this could be even more effective if we could accomodate
+       * cases such as "v.x = f();"  - would help with typical vertex
+       * transformation.
        */
       slang_ir_node *n;
       n = _slang_gen_function_call_name(A,
@@ -2023,6 +2099,14 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
         return n;
       }
 
+   case slang_oper_select:  /* b ? x : y */
+      {
+        slang_ir_node *n;
+         assert(oper->num_children == 3);
+        n = _slang_gen_select(A, oper );
+        return n;
+      }
+
    case slang_oper_asm:
       return _slang_gen_asm(A, oper, NULL);
    case slang_oper_call:
index e58256c9f1b2fadc38125fa4594877c91dcdf36a..1142bc6416b9975b57d217f261a9471844263bb4 100644 (file)
@@ -617,7 +617,8 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog)
       assert(n->Store);
       assert(n->Store->File != PROGRAM_UNDEFINED);
       assert(n->Store->Size > 0);
-      if (n->Var->isTemp)
+      assert(n->Store->Index < 0);
+      if (!n->Var || n->Var->isTemp)
          n->Store->Index = _slang_alloc_temp(vt, n->Store->Size);
       else
          n->Store->Index = _slang_alloc_var(vt, n->Store->Size);