dri: Get prototype for _mesa_destroy_compiler().
[mesa.git] / src / glsl / ir_validate.cpp
index 1dfac82826919c28b0faa825a3fd452625cb74c4..9ea11dd400ec8961e758e4086e4dec4b519bcc49 100644 (file)
@@ -67,6 +67,8 @@ public:
 
    virtual ir_visitor_status visit_leave(ir_expression *ir);
 
+   virtual ir_visitor_status visit_enter(ir_assignment *ir);
+
    static void validate_ir(ir_instruction *ir, void *data);
 
    ir_function *current_function;
@@ -80,14 +82,14 @@ ir_validate::visit(ir_dereference_variable *ir)
 {
    if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
       printf("ir_dereference_variable @ %p does not specify a variable %p\n",
-            ir, ir->var);
+            (void *) ir, (void *) ir->var);
       abort();
    }
 
    if (hash_table_find(ht, ir->var) == NULL) {
       printf("ir_dereference_variable @ %p specifies undeclared variable "
             "`%s' @ %p\n",
-            ir, ir->var->name, ir->var);
+            (void *) ir, ir->var->name, (void *) ir->var);
       abort();
    }
 
@@ -120,8 +122,8 @@ ir_validate::visit_enter(ir_function *ir)
       printf("Function definition nested inside another function "
             "definition:\n");
       printf("%s %p inside %s %p\n",
-            ir->name, ir,
-            this->current_function->name, this->current_function);
+            ir->name, (void *) ir,
+            this->current_function->name, (void *) this->current_function);
       abort();
    }
 
@@ -139,7 +141,7 @@ ir_validate::visit_enter(ir_function *ir)
 ir_visitor_status
 ir_validate::visit_leave(ir_function *ir)
 {
-   (void) ir;
+   assert(talloc_parent(ir->name) == ir);
 
    this->current_function = NULL;
    return visit_continue;
@@ -152,9 +154,9 @@ ir_validate::visit_enter(ir_function_signature *ir)
       printf("Function signature nested inside wrong function "
             "definition:\n");
       printf("%p inside %s %p instead of %s %p\n",
-            ir,
-            this->current_function->name, this->current_function,
-            ir->function_name(), ir->function());
+            (void *) ir,
+            this->current_function->name, (void *) this->current_function,
+            ir->function_name(), (void *) ir->function());
       abort();
    }
 
@@ -181,10 +183,14 @@ ir_validate::visit_leave(ir_expression *ir)
    case ir_unop_rcp:
    case ir_unop_rsq:
    case ir_unop_sqrt:
+      assert(ir->type == ir->operands[0]->type);
+      break;
+
    case ir_unop_exp:
    case ir_unop_log:
    case ir_unop_exp2:
    case ir_unop_log2:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
       assert(ir->type == ir->operands[0]->type);
       break;
 
@@ -217,6 +223,11 @@ ir_validate::visit_leave(ir_expression *ir)
       assert(ir->type->base_type == GLSL_TYPE_FLOAT);
       break;
 
+   case ir_unop_any:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->type == glsl_type::bool_type);
+      break;
+
    case ir_unop_trunc:
    case ir_unop_ceil:
    case ir_unop_floor:
@@ -313,10 +324,43 @@ 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)
+      assert(talloc_parent(ir->name) == ir);
+
    hash_table_insert(ht, ir, ir);
    return visit_continue;
 }
 
+ir_visitor_status
+ir_validate::visit_enter(ir_assignment *ir)
+{
+   const ir_dereference *const lhs = ir->lhs;
+   if (lhs->type->is_scalar() || lhs->type->is_vector()) {
+      if (ir->write_mask == 0) {
+        printf("Assignment LHS is %s, but write mask is 0:\n",
+               lhs->type->is_scalar() ? "scalar" : "vector");
+        ir->print();
+        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);
+
+      if ((invalid_mask & ir->write_mask) != 0) {
+        printf("Assignment write mask enables invalid components for "
+               "type %s:\n", lhs->type->name);
+        ir->print();
+        abort();
+      }
+   }
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
 void
 ir_validate::validate_ir(ir_instruction *ir, void *data)
 {
@@ -334,6 +378,8 @@ ir_validate::validate_ir(ir_instruction *ir, void *data)
 void
 check_node_type(ir_instruction *ir, void *data)
 {
+   (void) data;
+
    if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
       printf("Instruction node with unset type\n");
       ir->print(); printf("\n");