nir/lower_tex_projector: Don't use designated initializers
[mesa.git] / src / glsl / ir_validate.cpp
index 66a9800ce75156afe88e1ed7f311e85e01783560..cfe0df3dca6aa641567f45943ff3a5e3ccbc3063 100644 (file)
@@ -38,6 +38,8 @@
 #include "program/hash_table.h"
 #include "glsl_types.h"
 
+namespace {
+
 class ir_validate : public ir_hierarchical_visitor {
 public:
    ir_validate()
@@ -47,8 +49,8 @@ public:
 
       this->current_function = NULL;
 
-      this->callback = ir_validate::validate_ir;
-      this->data = ht;
+      this->callback_enter = ir_validate::validate_ir;
+      this->data_enter = ht;
    }
 
    ~ir_validate()
@@ -59,9 +61,9 @@ public:
    virtual ir_visitor_status visit(ir_variable *v);
    virtual ir_visitor_status visit(ir_dereference_variable *ir);
 
+   virtual ir_visitor_status visit_enter(ir_discard *ir);
    virtual ir_visitor_status visit_enter(ir_if *ir);
 
-   virtual ir_visitor_status visit_leave(ir_loop *ir);
    virtual ir_visitor_status visit_enter(ir_function *ir);
    virtual ir_visitor_status visit_leave(ir_function *ir);
    virtual ir_visitor_status visit_enter(ir_function_signature *ir);
@@ -81,6 +83,7 @@ public:
    struct hash_table *ht;
 };
 
+} /* anonymous namespace */
 
 ir_visitor_status
 ir_validate::visit(ir_dereference_variable *ir)
@@ -98,7 +101,7 @@ ir_validate::visit(ir_dereference_variable *ir)
       abort();
    }
 
-   this->validate_ir(ir, this->data);
+   this->validate_ir(ir, this->data_enter);
 
    return visit_continue;
 }
@@ -131,10 +134,10 @@ ir_validate::visit_enter(class ir_dereference_array *ir)
 }
 
 ir_visitor_status
-ir_validate::visit_enter(ir_if *ir)
+ir_validate::visit_enter(ir_discard *ir)
 {
-   if (ir->condition->type != glsl_type::bool_type) {
-      printf("ir_if condition %s type instead of bool.\n",
+   if (ir->condition && ir->condition->type != glsl_type::bool_type) {
+      printf("ir_discard condition %s type instead of bool.\n",
             ir->condition->type->name);
       ir->print();
       printf("\n");
@@ -144,37 +147,15 @@ ir_validate::visit_enter(ir_if *ir)
    return visit_continue;
 }
 
-
 ir_visitor_status
-ir_validate::visit_leave(ir_loop *ir)
+ir_validate::visit_enter(ir_if *ir)
 {
-   if (ir->counter != NULL) {
-      if ((ir->from == NULL) || (ir->to == NULL) || (ir->increment == NULL)) {
-        printf("ir_loop has invalid loop controls:\n"
-               "    counter:   %p\n"
-               "    from:      %p\n"
-               "    to:        %p\n"
-               "    increment: %p\n",
-               (void *) ir->counter, (void *) ir->from, (void *) ir->to,
-                (void *) ir->increment);
-        abort();
-      }
-
-      if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) {
-        printf("ir_loop has invalid comparitor %d\n", ir->cmp);
-        abort();
-      }
-   } else {
-      if ((ir->from != NULL) || (ir->to != NULL) || (ir->increment != NULL)) {
-        printf("ir_loop has invalid loop controls:\n"
-               "    counter:   %p\n"
-               "    from:      %p\n"
-               "    to:        %p\n"
-               "    increment: %p\n",
-               (void *) ir->counter, (void *) ir->from, (void *) ir->to,
-                (void *) ir->increment);
-        abort();
-      }
+   if (ir->condition->type != glsl_type::bool_type) {
+      printf("ir_if condition %s type instead of bool.\n",
+            ir->condition->type->name);
+      ir->print();
+      printf("\n");
+      abort();
    }
 
    return visit_continue;
@@ -201,14 +182,12 @@ ir_validate::visit_enter(ir_function *ir)
     */
    this->current_function = ir;
 
-   this->validate_ir(ir, this->data);
+   this->validate_ir(ir, this->data_enter);
 
    /* Verify that all of the things stored in the list of signatures are,
     * in fact, function signatures.
     */
-   foreach_list(node, &ir->signatures) {
-      ir_instruction *sig = (ir_instruction *) node;
-
+   foreach_in_list(ir_instruction, sig, &ir->signatures) {
       if (sig->ir_type != ir_type_function_signature) {
         printf("Non-signature in signature list of function `%s'\n",
                ir->name);
@@ -247,7 +226,7 @@ ir_validate::visit_enter(ir_function_signature *ir)
       abort();
    }
 
-   this->validate_ir(ir, this->data);
+   this->validate_ir(ir, this->data_enter);
 
    return visit_continue;
 }
@@ -277,6 +256,7 @@ ir_validate::visit_leave(ir_expression *ir)
    case ir_unop_log:
    case ir_unop_exp2:
    case ir_unop_log2:
+   case ir_unop_saturate:
       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
       assert(ir->type == ir->operands[0]->type);
       break;
@@ -348,12 +328,18 @@ ir_validate::visit_leave(ir_expression *ir)
    case ir_unop_ceil:
    case ir_unop_floor:
    case ir_unop_fract:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT ||
+             ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->operands[0]->type == ir->type);
+      break;
    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_dFdx_coarse:
+   case ir_unop_dFdx_fine:
    case ir_unop_dFdy:
+   case ir_unop_dFdy_coarse:
+   case ir_unop_dFdy_fine:
       assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
       assert(ir->operands[0]->type == ir->type);
       break;
@@ -371,6 +357,11 @@ ir_validate::visit_leave(ir_expression *ir)
       assert(ir->operands[0]->type == glsl_type::vec4_type);
       break;
 
+   case ir_unop_pack_double_2x32:
+      assert(ir->type == glsl_type::double_type);
+      assert(ir->operands[0]->type == glsl_type::uvec2_type);
+      break;
+
    case ir_unop_unpack_snorm_2x16:
    case ir_unop_unpack_unorm_2x16:
    case ir_unop_unpack_half_2x16:
@@ -390,6 +381,11 @@ ir_validate::visit_leave(ir_expression *ir)
       assert(ir->operands[0]->type == glsl_type::uint_type);
       break;
 
+   case ir_unop_unpack_double_2x32:
+      assert(ir->type == glsl_type::uvec2_type);
+      assert(ir->operands[0]->type == glsl_type::double_type);
+      break;
+
    case ir_unop_bitfield_reverse:
       assert(ir->operands[0]->type == ir->type);
       assert(ir->type->is_integer());
@@ -407,6 +403,50 @@ ir_validate::visit_leave(ir_expression *ir)
       /* XXX what can we assert here? */
       break;
 
+   case ir_unop_interpolate_at_centroid:
+      assert(ir->operands[0]->type == ir->type);
+      assert(ir->operands[0]->type->is_float());
+      break;
+
+   case ir_unop_d2f:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+      break;
+   case ir_unop_f2d:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type->base_type == GLSL_TYPE_DOUBLE);
+      break;
+   case ir_unop_d2i:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->type->base_type == GLSL_TYPE_INT);
+      break;
+   case ir_unop_i2d:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
+      assert(ir->type->base_type == GLSL_TYPE_DOUBLE);
+      break;
+   case ir_unop_d2u:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->type->base_type == GLSL_TYPE_UINT);
+      break;
+   case ir_unop_u2d:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
+      assert(ir->type->base_type == GLSL_TYPE_DOUBLE);
+      break;
+   case ir_unop_d2b:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      break;
+
+   case ir_unop_frexp_sig:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT ||
+             ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->type->base_type == GLSL_TYPE_DOUBLE);
+      break;
+   case ir_unop_frexp_exp:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT ||
+             ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->type->base_type == GLSL_TYPE_INT);
+      break;
    case ir_binop_add:
    case ir_binop_sub:
    case ir_binop_mul:
@@ -415,6 +455,9 @@ ir_validate::visit_leave(ir_expression *ir)
    case ir_binop_min:
    case ir_binop_max:
    case ir_binop_pow:
+      assert(ir->operands[0]->type->base_type ==
+             ir->operands[1]->type->base_type);
+
       if (ir->operands[0]->type->is_scalar())
         assert(ir->operands[1]->type == ir->type);
       else if (ir->operands[1]->type->is_scalar())
@@ -426,6 +469,19 @@ ir_validate::visit_leave(ir_expression *ir)
       }
       break;
 
+   case ir_binop_imul_high:
+      assert(ir->type == ir->operands[0]->type);
+      assert(ir->type == ir->operands[1]->type);
+      assert(ir->type->is_integer());
+      break;
+
+   case ir_binop_carry:
+   case ir_binop_borrow:
+      assert(ir->type == ir->operands[0]->type);
+      assert(ir->type == ir->operands[1]->type);
+      assert(ir->type->base_type == GLSL_TYPE_UINT);
+      break;
+
    case ir_binop_less:
    case ir_binop_greater:
    case ir_binop_lequal:
@@ -485,14 +541,16 @@ ir_validate::visit_leave(ir_expression *ir)
    case ir_binop_logic_and:
    case ir_binop_logic_xor:
    case ir_binop_logic_or:
-      assert(ir->type == glsl_type::bool_type);
-      assert(ir->operands[0]->type == glsl_type::bool_type);
-      assert(ir->operands[1]->type == glsl_type::bool_type);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->operands[1]->type->base_type == GLSL_TYPE_BOOL);
       break;
 
    case ir_binop_dot:
-      assert(ir->type == glsl_type::float_type);
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type == glsl_type::float_type ||
+             ir->type == glsl_type::double_type);
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT ||
+             ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
       assert(ir->operands[0]->type->is_vector());
       assert(ir->operands[0]->type == ir->operands[1]->type);
       break;
@@ -510,7 +568,6 @@ ir_validate::visit_leave(ir_expression *ir)
       break;
 
    case ir_binop_ubo_load:
-      assert(ir->operands[0]->as_constant());
       assert(ir->operands[0]->type == glsl_type::uint_type);
 
       assert(ir->operands[1]->type == glsl_type::uint_type);
@@ -518,7 +575,8 @@ ir_validate::visit_leave(ir_expression *ir)
 
    case ir_binop_ldexp:
       assert(ir->operands[0]->type == ir->type);
-      assert(ir->operands[0]->type->is_float());
+      assert(ir->operands[0]->type->is_float() ||
+             ir->operands[0]->type->is_double());
       assert(ir->operands[1]->type->base_type == GLSL_TYPE_INT);
       assert(ir->operands[0]->type->components() ==
              ir->operands[1]->type->components());
@@ -530,11 +588,34 @@ ir_validate::visit_leave(ir_expression *ir)
              && ir->operands[1]->type->is_integer());
       break;
 
+   case ir_binop_interpolate_at_offset:
+      assert(ir->operands[0]->type == ir->type);
+      assert(ir->operands[0]->type->is_float());
+      assert(ir->operands[1]->type->components() == 2);
+      assert(ir->operands[1]->type->is_float());
+      break;
+
+   case ir_binop_interpolate_at_sample:
+      assert(ir->operands[0]->type == ir->type);
+      assert(ir->operands[0]->type->is_float());
+      assert(ir->operands[1]->type == glsl_type::int_type);
+      break;
+
    case ir_triop_fma:
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT ||
+             ir->type->base_type == GLSL_TYPE_DOUBLE);
+      assert(ir->type == ir->operands[0]->type);
+      assert(ir->type == ir->operands[1]->type);
+      assert(ir->type == ir->operands[2]->type);
+      break;
+
    case ir_triop_lrp:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT ||
+             ir->operands[0]->type->base_type == GLSL_TYPE_DOUBLE);
       assert(ir->operands[0]->type == ir->operands[1]->type);
-      assert(ir->operands[2]->type == ir->operands[0]->type || ir->operands[2]->type == glsl_type::float_type);
+      assert(ir->operands[2]->type == ir->operands[0]->type ||
+             ir->operands[2]->type == glsl_type::float_type ||
+             ir->operands[2]->type == glsl_type::double_type);
       break;
 
    case ir_triop_csel:
@@ -646,7 +727,7 @@ ir_validate::visit(ir_variable *ir)
     * in the ir_dereference_variable handler to ensure that a variable is
     * declared before it is dereferenced.
     */
-   if (ir->name)
+   if (ir->name && ir->is_name_ralloced())
       assert(ralloc_parent(ir->name) == ir);
 
    hash_table_insert(ht, ir, ir);
@@ -657,21 +738,54 @@ ir_validate::visit(ir_variable *ir)
     * to be out of bounds.
     */
    if (ir->type->array_size() > 0) {
-      if (ir->max_array_access >= ir->type->length) {
+      if (ir->data.max_array_access >= ir->type->length) {
         printf("ir_variable has maximum access out of bounds (%d vs %d)\n",
-               ir->max_array_access, ir->type->length - 1);
+               ir->data.max_array_access, ir->type->length - 1);
         ir->print();
         abort();
       }
    }
 
-   if (ir->constant_initializer != NULL && !ir->has_initializer) {
+   /* If a variable is an interface block (or an array of interface blocks),
+    * verify that the maximum array index for each interface member is in
+    * bounds.
+    */
+   if (ir->is_interface_instance()) {
+      const glsl_struct_field *fields =
+         ir->get_interface_type()->fields.structure;
+      for (unsigned i = 0; i < ir->get_interface_type()->length; i++) {
+         if (fields[i].type->array_size() > 0) {
+            const unsigned *const max_ifc_array_access =
+               ir->get_max_ifc_array_access();
+
+            assert(max_ifc_array_access != NULL);
+
+            if (max_ifc_array_access[i] >= fields[i].type->length) {
+               printf("ir_variable has maximum access out of bounds for "
+                      "field %s (%d vs %d)\n", fields[i].name,
+                      max_ifc_array_access[i], fields[i].type->length);
+               ir->print();
+               abort();
+            }
+         }
+      }
+   }
+
+   if (ir->constant_initializer != NULL && !ir->data.has_initializer) {
       printf("ir_variable didn't have an initializer, but has a constant "
             "initializer value.\n");
       ir->print();
       abort();
    }
 
+   if (ir->data.mode == ir_var_uniform
+       && is_gl_identifier(ir->name)
+       && ir->get_state_slots() == NULL) {
+      printf("built-in uniform has no state\n");
+      ir->print();
+      abort();
+   }
+
    return visit_continue;
 }
 
@@ -702,7 +816,7 @@ ir_validate::visit_enter(ir_assignment *ir)
       }
    }
 
-   this->validate_ir(ir, this->data);
+   this->validate_ir(ir, this->data_enter);
 
    return visit_continue;
 }
@@ -747,8 +861,8 @@ ir_validate::visit_enter(ir_call *ir)
          printf("ir_call parameter type mismatch:\n");
          goto dump_ir;
       }
-      if (formal_param->mode == ir_var_function_out
-          || formal_param->mode == ir_var_function_inout) {
+      if (formal_param->data.mode == ir_var_function_out
+          || formal_param->data.mode == ir_var_function_inout) {
          if (!actual_param->is_lvalue()) {
             printf("ir_call out/inout parameters must be lvalues:\n");
             goto dump_ir;
@@ -787,7 +901,7 @@ check_node_type(ir_instruction *ir, void *data)
 {
    (void) data;
 
-   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
+   if (ir->ir_type >= ir_type_max) {
       printf("Instruction node with unset type\n");
       ir->print(); printf("\n");
    }
@@ -808,9 +922,7 @@ validate_ir_tree(exec_list *instructions)
 
    v.run(instructions);
 
-   foreach_iter(exec_list_iterator, iter, *instructions) {
-      ir_instruction *ir = (ir_instruction *)iter.get();
-
+   foreach_in_list(ir_instruction, ir, instructions) {
       visit_tree(ir, check_node_type, NULL);
    }
 #endif