ir_to_mesa: Support gl_FragData[] output.
[mesa.git] / ir_function.cpp
index 1ff5b203ccf0b0e181da4c4bae9863f829923b9e..5db93f67fb8cdb5a8f3b2bcf074e69b3c6a06619 100644 (file)
@@ -35,16 +35,18 @@ type_compare(const glsl_type *a, const glsl_type *b)
    switch (a->base_type) {
    case GLSL_TYPE_UINT:
    case GLSL_TYPE_INT:
-   case GLSL_TYPE_FLOAT:
    case GLSL_TYPE_BOOL:
-      if ((a->vector_elements != b->vector_elements)
-         || (a->matrix_rows != b->matrix_rows))
+      /* There is no implicit conversion to or from integer types or bool.
+       */
+      if ((a->is_integer() != b->is_integer())
+         || (a->is_boolean() != b->is_boolean()))
         return -1;
 
-      /* There is no implicit conversion to or from bool.
-       */
-      if ((a->base_type == GLSL_TYPE_BOOL)
-         || (b->base_type == GLSL_TYPE_BOOL))
+      /* FALLTHROUGH */
+
+   case GLSL_TYPE_FLOAT:
+      if ((a->vector_elements != b->vector_elements)
+         || (a->matrix_columns != b->matrix_columns))
         return -1;
 
       return 1;
@@ -124,13 +126,10 @@ parameter_lists_match(exec_list *list_a, exec_list *list_b)
         break;
 
       case ir_var_out:
-        /* FINISHME: Make sure that actual is a valid lvalue. */
         score = type_compare(actual->type, param->type);
         break;
 
       case ir_var_inout:
-        /* FINISHME: Make sure that actual is a valid lvalue. */
-
         /* Since there are no bi-directional automatic conversions (e.g.,
          * there is int -> float but no float -> int), inout parameters must
          * be exact matches.
@@ -181,3 +180,46 @@ ir_function::matching_signature(exec_list *actual_parameters)
 
    return match;
 }
+
+
+static bool
+parameter_lists_match_exact(exec_list *list_a, exec_list *list_b)
+{
+   exec_list_iterator iter_a = list_a->iterator();
+   exec_list_iterator iter_b = list_b->iterator();
+
+   while (iter_a.has_next() && iter_b.has_next()) {
+      ir_variable *a = (ir_variable *)iter_a.get();
+      ir_variable *b = (ir_variable *)iter_b.get();
+
+      /* If the types of the parameters do not match, the parameters lists
+       * are different.
+       */
+      if (a->type != b->type)
+         return false;
+
+      iter_a.next();
+      iter_b.next();
+   }
+
+   /* Unless both lists are exhausted, they differ in length and, by
+    * definition, do not match.
+    */
+   if (iter_a.has_next() != iter_b.has_next())
+      return false;
+
+   return true;
+}
+
+ir_function_signature *
+ir_function::exact_matching_signature(exec_list *actual_parameters)
+{
+   foreach_iter(exec_list_iterator, iter, signatures) {
+      ir_function_signature *const sig =
+        (ir_function_signature *) iter.get();
+
+      if (parameter_lists_match_exact(&sig->parameters, actual_parameters))
+        return sig;
+   }
+   return NULL;
+}