glsl: Refactor AST-to-HIR code handling variable initializers
[mesa.git] / src / glsl / ir_validate.cpp
index 8e8259036447d52a4ce756f1b1541a74cf8f24ac..44d7549ea285bda27b48cbf88b3fd012d565d241 100644 (file)
@@ -67,6 +67,7 @@ public:
    virtual ir_visitor_status visit_enter(ir_function_signature *ir);
 
    virtual ir_visitor_status visit_leave(ir_expression *ir);
+   virtual ir_visitor_status visit_leave(ir_swizzle *ir);
 
    virtual ir_visitor_status visit_enter(ir_assignment *ir);
 
@@ -124,7 +125,8 @@ ir_validate::visit_leave(ir_loop *ir)
                "    from:      %p\n"
                "    to:        %p\n"
                "    increment: %p\n",
-               ir->counter, ir->from, ir->to, ir->increment);
+               (void *) ir->counter, (void *) ir->from, (void *) ir->to,
+                (void *) ir->increment);
         abort();
       }
 
@@ -139,7 +141,8 @@ ir_validate::visit_leave(ir_loop *ir)
                "    from:      %p\n"
                "    to:        %p\n"
                "    increment: %p\n",
-               ir->counter, ir->from, ir->to, ir->increment);
+               (void *) ir->counter, (void *) ir->from, (void *) ir->to,
+                (void *) ir->increment);
         abort();
       }
    }
@@ -176,7 +179,7 @@ ir_validate::visit_enter(ir_function *ir)
 ir_visitor_status
 ir_validate::visit_leave(ir_function *ir)
 {
-   assert(talloc_parent(ir->name) == ir);
+   assert(ralloc_parent(ir->name) == ir);
 
    this->current_function = NULL;
    return visit_continue;
@@ -264,17 +267,24 @@ ir_validate::visit_leave(ir_expression *ir)
       break;
 
    case ir_unop_trunc:
+   case ir_unop_round_even:
    case ir_unop_ceil:
    case ir_unop_floor:
    case ir_unop_fract:
    case ir_unop_sin:
    case ir_unop_cos:
+   case ir_unop_sin_reduced:
+   case ir_unop_cos_reduced:
    case ir_unop_dFdx:
    case ir_unop_dFdy:
       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
       assert(ir->operands[0]->type == ir->type);
       break;
 
+   case ir_unop_noise:
+      /* XXX what can we assert here? */
+      break;
+
    case ir_binop_add:
    case ir_binop_sub:
    case ir_binop_mul:
@@ -293,24 +303,30 @@ ir_validate::visit_leave(ir_expression *ir)
         assert(ir->operands[0]->type == ir->type);
       }
       break;
+
    case ir_binop_less:
    case ir_binop_greater:
    case ir_binop_lequal:
    case ir_binop_gequal:
-      /* GLSL < > <= >= operators take scalar floats/ints, but in the
-       * IR we may want to do them for vectors instead to support the
-       * lessEqual() and friends builtins.
+   case ir_binop_equal:
+   case ir_binop_nequal:
+      /* The semantics of the IR operators differ from the GLSL <, >, <=, >=,
+       * ==, and != operators.  The IR operators perform a component-wise
+       * comparison on scalar or vector types and return a boolean scalar or
+       * vector type of the same size.
        */
-      assert(ir->type == glsl_type::bool_type);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
       assert(ir->operands[0]->type == ir->operands[1]->type);
+      assert(ir->operands[0]->type->is_vector()
+            || ir->operands[0]->type->is_scalar());
+      assert(ir->operands[0]->type->vector_elements
+            == ir->type->vector_elements);
       break;
 
-   case ir_binop_equal:
-   case ir_binop_nequal:
-      /* GLSL == and != operate on vectors and return a bool, and the
-       * IR matches that.  We may want to switch up the IR to work on
-       * vectors and return a bvec and make the operators break down
-       * to ANDing/ORing the results of the vector comparison.
+   case ir_binop_all_equal:
+   case ir_binop_any_nequal:
+      /* GLSL == and != operate on scalars, vectors, matrices and arrays, and
+       * return a scalar boolean.  The IR matches that.
        */
       assert(ir->type == glsl_type::bool_type);
       assert(ir->operands[0]->type == ir->operands[1]->type);
@@ -318,14 +334,31 @@ ir_validate::visit_leave(ir_expression *ir)
 
    case ir_binop_lshift:
    case ir_binop_rshift:
+      assert(ir->operands[0]->type->is_integer() &&
+             ir->operands[1]->type->is_integer());
+      if (ir->operands[0]->type->is_scalar()) {
+          assert(ir->operands[1]->type->is_scalar());
+      }
+      if (ir->operands[0]->type->is_vector() &&
+          ir->operands[1]->type->is_vector()) {
+          assert(ir->operands[0]->type->components() ==
+                 ir->operands[1]->type->components());
+      }
+      assert(ir->type == ir->operands[0]->type);
+      break;
+
    case ir_binop_bit_and:
    case ir_binop_bit_xor:
    case ir_binop_bit_or:
-      assert(ir->operands[0]->type == ir->operands[1]->type);
-      assert(ir->type == ir->operands[0]->type);
-      assert(ir->type->base_type == GLSL_TYPE_INT ||
-            ir->type->base_type == GLSL_TYPE_UINT);
-      break;
+       assert(ir->operands[0]->type->base_type ==
+              ir->operands[1]->type->base_type);
+       assert(ir->type->is_integer());
+       if (ir->operands[0]->type->is_vector() &&
+           ir->operands[1]->type->is_vector()) {
+           assert(ir->operands[0]->type->vector_elements ==
+                  ir->operands[1]->type->vector_elements);
+       }
+       break;
 
    case ir_binop_logic_and:
    case ir_binop_logic_xor:
@@ -338,14 +371,71 @@ ir_validate::visit_leave(ir_expression *ir)
    case ir_binop_dot:
       assert(ir->type == glsl_type::float_type);
       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->operands[0]->type->is_vector());
       assert(ir->operands[0]->type == ir->operands[1]->type);
       break;
 
-   case ir_binop_cross:
-      assert(ir->operands[0]->type == glsl_type::vec3_type);
-      assert(ir->operands[1]->type == glsl_type::vec3_type);
-      assert(ir->type == glsl_type::vec3_type);
-      break;
+   case ir_quadop_vector:
+      /* The vector operator collects some number of scalars and generates a
+       * vector from them.
+       *
+       *  - All of the operands must be scalar.
+       *  - Number of operands must matche the size of the resulting vector.
+       *  - Base type of the operands must match the base type of the result.
+       */
+      assert(ir->type->is_vector());
+      switch (ir->type->vector_elements) {
+      case 2:
+        assert(ir->operands[0]->type->is_scalar());
+        assert(ir->operands[0]->type->base_type == ir->type->base_type);
+        assert(ir->operands[1]->type->is_scalar());
+        assert(ir->operands[1]->type->base_type == ir->type->base_type);
+        assert(ir->operands[2] == NULL);
+        assert(ir->operands[3] == NULL);
+        break;
+      case 3:
+        assert(ir->operands[0]->type->is_scalar());
+        assert(ir->operands[0]->type->base_type == ir->type->base_type);
+        assert(ir->operands[1]->type->is_scalar());
+        assert(ir->operands[1]->type->base_type == ir->type->base_type);
+        assert(ir->operands[2]->type->is_scalar());
+        assert(ir->operands[2]->type->base_type == ir->type->base_type);
+        assert(ir->operands[3] == NULL);
+        break;
+      case 4:
+        assert(ir->operands[0]->type->is_scalar());
+        assert(ir->operands[0]->type->base_type == ir->type->base_type);
+        assert(ir->operands[1]->type->is_scalar());
+        assert(ir->operands[1]->type->base_type == ir->type->base_type);
+        assert(ir->operands[2]->type->is_scalar());
+        assert(ir->operands[2]->type->base_type == ir->type->base_type);
+        assert(ir->operands[3]->type->is_scalar());
+        assert(ir->operands[3]->type->base_type == ir->type->base_type);
+        break;
+      default:
+        /* The is_vector assertion above should prevent execution from ever
+         * getting here.
+         */
+        assert(!"Should not get here.");
+        break;
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_swizzle *ir)
+{
+   int chans[4] = {ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w};
+
+   for (unsigned int i = 0; i < ir->type->vector_elements; i++) {
+      if (chans[i] >= ir->val->type->vector_elements) {
+        printf("ir_swizzle @ %p specifies a channel not present "
+               "in the value.\n", (void *) ir);
+        ir->print();
+        abort();
+      }
    }
 
    return visit_continue;
@@ -360,7 +450,7 @@ ir_validate::visit(ir_variable *ir)
     * declared before it is dereferenced.
     */
    if (ir->name)
-      assert(talloc_parent(ir->name) == ir);
+      assert(ralloc_parent(ir->name) == ir);
 
    hash_table_insert(ht, ir, ir);
    return visit_continue;
@@ -378,14 +468,16 @@ ir_validate::visit_enter(ir_assignment *ir)
         abort();
       }
 
-      /* Mask of fields that do not exist in the destination.  These should
-       * not be written by the assignment.
-       */
-      const unsigned invalid_mask = ~((1U << lhs->type->components()) - 1);
+      int lhs_components = 0;
+      for (int i = 0; i < 4; i++) {
+        if (ir->write_mask & (1 << i))
+           lhs_components++;
+      }
 
-      if ((invalid_mask & ir->write_mask) != 0) {
-        printf("Assignment write mask enables invalid components for "
-               "type %s:\n", lhs->type->name);
+      if (lhs_components != ir->rhs->type->vector_elements) {
+        printf("Assignment count of LHS write mask channels enabled not\n"
+               "matching RHS vector size (%d LHS, %d RHS).\n",
+               lhs_components, ir->rhs->type->vector_elements);
         ir->print();
         abort();
       }