glsl: Link glsl_test with pthreads library.
[mesa.git] / src / glsl / ir_validate.cpp
index d6abc8eb5a828eca79574c3f8fdb6fb49c8af22b..6d5633916ba2fe40d6805d0971c96b2ec863ede9 100644 (file)
@@ -49,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()
@@ -63,7 +63,6 @@ public:
 
    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);
@@ -101,7 +100,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;
 }
@@ -148,42 +147,6 @@ ir_validate::visit_enter(ir_if *ir)
 }
 
 
-ir_visitor_status
-ir_validate::visit_leave(ir_loop *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();
-      }
-   }
-
-   return visit_continue;
-}
-
-
 ir_visitor_status
 ir_validate::visit_enter(ir_function *ir)
 {
@@ -204,14 +167,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);
@@ -250,7 +211,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;
 }
@@ -280,6 +241,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;
@@ -356,7 +318,11 @@ ir_validate::visit_leave(ir_expression *ir)
    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;
@@ -410,6 +376,11 @@ 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_binop_add:
    case ir_binop_sub:
    case ir_binop_mul:
@@ -418,6 +389,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())
@@ -526,7 +500,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);
@@ -546,6 +519,19 @@ 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);
       assert(ir->type == ir->operands[0]->type);
@@ -668,7 +654,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);
@@ -679,21 +665,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;
 }
 
@@ -724,7 +743,7 @@ ir_validate::visit_enter(ir_assignment *ir)
       }
    }
 
-   this->validate_ir(ir, this->data);
+   this->validate_ir(ir, this->data_enter);
 
    return visit_continue;
 }
@@ -769,8 +788,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;
@@ -809,7 +828,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");
    }
@@ -830,9 +849,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