android: generate files by $(call es-gen)
[mesa.git] / src / glsl / ir_function.cpp
index 44118103c757581b56f2d5caba6c44a7f594542b..2b2643c64a2c0b4718c13cebb4669b14b0c96a90 100644 (file)
@@ -24,6 +24,7 @@
 #include "glsl_types.h"
 #include "ir.h"
 #include "glsl_parser_extras.h"
+#include "main/errors.h"
 
 typedef enum {
    PARAMETER_LIST_NO_MATCH,
@@ -192,6 +193,66 @@ is_better_parameter_match(parameter_match_t a_match,
 }
 
 
+static bool
+is_best_inexact_overload(const exec_list *actual_parameters,
+                         ir_function_signature **matches,
+                         int num_matches,
+                         ir_function_signature *sig)
+{
+   /* From section 6.1 of the GLSL 4.00 spec (and the ARB_gpu_shader5 spec):
+    *
+    * "A function definition A is considered a better
+    * match than function definition B if:
+    *
+    *   * for at least one function argument, the conversion for that argument
+    *     in A is better than the corresponding conversion in B; and
+    *
+    *   * there is no function argument for which the conversion in B is better
+    *     than the corresponding conversion in A.
+    *
+    * If a single function definition is considered a better match than every
+    * other matching function definition, it will be used.  Otherwise, a
+    * semantic error occurs and the shader will fail to compile."
+    */
+   for (ir_function_signature **other = matches;
+        other < matches + num_matches; other++) {
+      if (*other == sig)
+         continue;
+
+      const exec_node *node_a = sig->parameters.head;
+      const exec_node *node_b = (*other)->parameters.head;
+      const exec_node *node_p = actual_parameters->head;
+
+      bool better_for_some_parameter = false;
+
+      for (/* empty */
+           ; !node_a->is_tail_sentinel()
+           ; node_a = node_a->next,
+             node_b = node_b->next,
+             node_p = node_p->next) {
+         parameter_match_t a_match = get_parameter_match_type(
+               (const ir_variable *)node_a,
+               (const ir_rvalue *)node_p);
+         parameter_match_t b_match = get_parameter_match_type(
+               (const ir_variable *)node_b,
+               (const ir_rvalue *)node_p);
+
+         if (is_better_parameter_match(a_match, b_match))
+               better_for_some_parameter = true;
+
+         if (is_better_parameter_match(b_match, a_match))
+               return false;     /* B is better for this parameter */
+      }
+
+      if (!better_for_some_parameter)
+         return false;     /* A must be better than B for some parameter */
+
+   }
+
+   return true;
+}
+
+
 static ir_function_signature *
 choose_best_inexact_overload(_mesa_glsl_parse_state *state,
                              const exec_list *actual_parameters,
@@ -204,24 +265,39 @@ choose_best_inexact_overload(_mesa_glsl_parse_state *state,
    if (num_matches == 1)
       return *matches;
 
+   /* Without GLSL 4.0 / ARB_gpu_shader5, there is no overload resolution
+    * among multiple inexact matches. Note that state may be NULL here if
+    * called from the linker; in that case we assume everything supported in
+    * any GLSL version is available. */
+   if (!state || state->is_version(400, 0) || state->ARB_gpu_shader5_enable) {
+      for (ir_function_signature **sig = matches; sig < matches + num_matches; sig++) {
+         if (is_best_inexact_overload(actual_parameters, matches, num_matches, *sig))
+            return *sig;
+      }
+   }
+
    return NULL;   /* no best candidate */
 }
 
 
 ir_function_signature *
 ir_function::matching_signature(_mesa_glsl_parse_state *state,
-                                const exec_list *actual_parameters)
+                                const exec_list *actual_parameters,
+                                bool allow_builtins)
 {
    bool is_exact;
-   return matching_signature(state, actual_parameters, &is_exact);
+   return matching_signature(state, actual_parameters, allow_builtins,
+                             &is_exact);
 }
 
 ir_function_signature *
 ir_function::matching_signature(_mesa_glsl_parse_state *state,
                                 const exec_list *actual_parameters,
+                                bool allow_builtins,
                                 bool *is_exact)
 {
    ir_function_signature **inexact_matches = NULL;
+   ir_function_signature **inexact_matches_temp;
    ir_function_signature *match = NULL;
    int num_inexact_matches = 0;
 
@@ -235,11 +311,10 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
     *  multiple ways to apply these conversions to the actual arguments of a
     *  call such that the call can be made to match multiple signatures."
     */
-   foreach_list(n, &this->signatures) {
-      ir_function_signature *const sig = (ir_function_signature *) n;
-
+   foreach_in_list(ir_function_signature, sig, &this->signatures) {
       /* Skip over any built-ins that aren't available in this shader. */
-      if (sig->is_builtin() && !sig->is_builtin_available(state))
+      if (sig->is_builtin() && (!allow_builtins ||
+                                !sig->is_builtin_available(state)))
          continue;
 
       switch (parameter_lists_match(state, & sig->parameters, actual_parameters)) {
@@ -248,11 +323,16 @@ ir_function::matching_signature(_mesa_glsl_parse_state *state,
          free(inexact_matches);
          return sig;
       case PARAMETER_LIST_INEXACT_MATCH:
-         inexact_matches = (ir_function_signature **)
+         inexact_matches_temp = (ir_function_signature **)
                realloc(inexact_matches,
                        sizeof(*inexact_matches) *
                        (num_inexact_matches + 1));
-         assert(inexact_matches);
+         if (inexact_matches_temp == NULL) {
+            _mesa_error_no_memory(__func__);
+            free(inexact_matches);
+            return NULL;
+         }
+         inexact_matches = inexact_matches_temp;
          inexact_matches[num_inexact_matches++] = sig;
          continue;
       case PARAMETER_LIST_NO_MATCH:
@@ -309,9 +389,7 @@ ir_function_signature *
 ir_function::exact_matching_signature(_mesa_glsl_parse_state *state,
                                       const exec_list *actual_parameters)
 {
-   foreach_list(n, &this->signatures) {
-      ir_function_signature *const sig = (ir_function_signature *) n;
-
+   foreach_in_list(ir_function_signature, sig, &this->signatures) {
       /* Skip over any built-ins that aren't available in this shader. */
       if (sig->is_builtin() && !sig->is_builtin_available(state))
          continue;