X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fir_function.cpp;h=fe4209c77cce58b53f467f64c3c3339765ce2940;hb=93c8692ce92d396f0a4db5bc91d8e7322fa7dd50;hp=5db93f67fb8cdb5a8f3b2bcf074e69b3c6a06619;hpb=bcc13b74443137043e8a34f8cb64a5add0d8af93;p=mesa.git diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp index 5db93f67fb8..fe4209c77cc 100644 --- a/src/glsl/ir_function.cpp +++ b/src/glsl/ir_function.cpp @@ -24,195 +24,186 @@ #include "glsl_types.h" #include "ir.h" -int -type_compare(const glsl_type *a, const glsl_type *b) +typedef enum { + PARAMETER_LIST_NO_MATCH, + PARAMETER_LIST_EXACT_MATCH, + PARAMETER_LIST_INEXACT_MATCH /*< Match requires implicit conversion. */ +} parameter_list_match_t; + +/** + * \brief Check if two parameter lists match. + * + * \param list_a Parameters of the function definition. + * \param list_b Actual parameters passed to the function. + * \see matching_signature() + */ +static parameter_list_match_t +parameter_lists_match(const exec_list *list_a, const exec_list *list_b) { - /* If the types are the same, they trivially match. - */ - if (a == b) - return 0; - - switch (a->base_type) { - case GLSL_TYPE_UINT: - case GLSL_TYPE_INT: - case GLSL_TYPE_BOOL: - /* 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; - - /* FALLTHROUGH */ + const exec_node *node_a = list_a->head; + const exec_node *node_b = list_b->head; - case GLSL_TYPE_FLOAT: - if ((a->vector_elements != b->vector_elements) - || (a->matrix_columns != b->matrix_columns)) - return -1; + /* This is set to true if there is an inexact match requiring an implicit + * conversion. */ + bool inexact_match = false; - return 1; - - case GLSL_TYPE_SAMPLER: - case GLSL_TYPE_STRUCT: - /* Samplers and structures must match exactly. - */ - return -1; - - case GLSL_TYPE_ARRAY: - if ((b->base_type != GLSL_TYPE_ARRAY) - || (a->length != b->length)) - return -1; - - /* From GLSL 1.50 spec, page 27 (page 33 of the PDF): - * "There are no implicit array or structure conversions." - * - * If the comparison of the array element types detects that a conversion - * would be required, the array types do not match. - */ - return (type_compare(a->fields.array, b->fields.array) == 0) ? 0 : -1; - - case GLSL_TYPE_FUNCTION: - case GLSL_TYPE_VOID: - case GLSL_TYPE_ERROR: - default: - /* These are all error conditions. It is invalid for a parameter to - * a function to be declared as error, void, or a function. - */ - return -1; - } - - /* This point should be unreachable. - */ - assert(0); -} - - -static int -parameter_lists_match(exec_list *list_a, exec_list *list_b) -{ - exec_list_iterator iter_a = list_a->iterator(); - exec_list_iterator iter_b = list_b->iterator(); - int total_score = 0; - - for (/* empty */ ; iter_a.has_next(); iter_a.next(), iter_b.next()) { + for (/* empty */ + ; !node_a->is_tail_sentinel() + ; node_a = node_a->next, node_b = node_b->next) { /* If all of the parameters from the other parameter list have been * exhausted, the lists have different length and, by definition, * do not match. */ - if (!iter_b.has_next()) - return -1; + if (node_b->is_tail_sentinel()) + return PARAMETER_LIST_NO_MATCH; - const ir_variable *const param = (ir_variable *) iter_a.get(); - const ir_instruction *const actual = (ir_instruction *) iter_b.get(); + const ir_variable *const param = (ir_variable *) node_a; + const ir_rvalue *const actual = (ir_rvalue *) node_b; - /* Determine whether or not the types match. If the types are an - * exact match, the match score is zero. If the types don't match - * but the actual parameter can be coerced to the type of the declared - * parameter, the match score is one. - */ - int score; + if (param->type == actual->type) + continue; + + /* Try to find an implicit conversion from actual to param. */ + inexact_match = true; switch ((enum ir_variable_mode)(param->mode)) { case ir_var_auto: case ir_var_uniform: + case ir_var_temporary: /* These are all error conditions. It is invalid for a parameter to * a function to be declared as auto (not in, out, or inout) or * as uniform. */ assert(0); - return -1; + return PARAMETER_LIST_NO_MATCH; - case ir_var_in: - score = type_compare(param->type, actual->type); + case ir_var_const_in: + case ir_var_function_in: + if (!actual->type->can_implicitly_convert_to(param->type)) + return PARAMETER_LIST_NO_MATCH; break; - case ir_var_out: - score = type_compare(actual->type, param->type); + case ir_var_function_out: + if (!param->type->can_implicitly_convert_to(actual->type)) + return PARAMETER_LIST_NO_MATCH; break; - case ir_var_inout: + case ir_var_function_inout: /* Since there are no bi-directional automatic conversions (e.g., * there is int -> float but no float -> int), inout parameters must * be exact matches. */ - score = (type_compare(actual->type, param->type) == 0) ? 0 : -1; - break; - } - - if (score < 0) - return -1; + return PARAMETER_LIST_NO_MATCH; - total_score += score; + default: + assert(false); + return PARAMETER_LIST_NO_MATCH; + } } /* If all of the parameters from the other parameter list have been * exhausted, the lists have different length and, by definition, do not * match. */ - if (iter_b.has_next()) - return -1; + if (!node_b->is_tail_sentinel()) + return PARAMETER_LIST_NO_MATCH; - return total_score; + if (inexact_match) + return PARAMETER_LIST_INEXACT_MATCH; + else + return PARAMETER_LIST_EXACT_MATCH; } -const ir_function_signature * -ir_function::matching_signature(exec_list *actual_parameters) +ir_function_signature * +ir_function::matching_signature(const exec_list *actual_parameters) +{ + bool is_exact; + return matching_signature(actual_parameters, &is_exact); +} + +ir_function_signature * +ir_function::matching_signature(const exec_list *actual_parameters, + bool *is_exact) { ir_function_signature *match = NULL; - + bool multiple_inexact_matches = false; + + /* From page 42 (page 49 of the PDF) of the GLSL 1.20 spec: + * + * "If an exact match is found, the other signatures are ignored, and + * the exact match is used. Otherwise, if no exact match is found, then + * the implicit conversions in Section 4.1.10 "Implicit Conversions" will + * be applied to the calling arguments if this can make their types match + * a signature. In this case, it is a semantic error if there are + * 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_iter(exec_list_iterator, iter, signatures) { ir_function_signature *const sig = (ir_function_signature *) iter.get(); - const int score = parameter_lists_match(& sig->parameters, - actual_parameters); - - if (score == 0) + switch (parameter_lists_match(& sig->parameters, actual_parameters)) { + case PARAMETER_LIST_EXACT_MATCH: + *is_exact = true; return sig; - - if (score > 0) { - if (match != NULL) - return NULL; - - match = sig; + case PARAMETER_LIST_INEXACT_MATCH: + if (match == NULL) + match = sig; + else + multiple_inexact_matches = true; + continue; + case PARAMETER_LIST_NO_MATCH: + continue; + default: + assert(false); + return NULL; } } + /* There is no exact match (we would have returned it by now). If there + * are multiple inexact matches, the call is ambiguous, which is an error. + * + * FINISHME: Report a decent error. Returning NULL will likely result in + * FINISHME: a "no matching signature" error; it should report that the + * FINISHME: call is ambiguous. But reporting errors from here is hard. + */ + *is_exact = false; + + if (multiple_inexact_matches) + return NULL; + return match; } static bool -parameter_lists_match_exact(exec_list *list_a, exec_list *list_b) +parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b) { - exec_list_iterator iter_a = list_a->iterator(); - exec_list_iterator iter_b = list_b->iterator(); + const exec_node *node_a = list_a->head; + const exec_node *node_b = list_b->head; - 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(); + for (/* empty */ + ; !node_a->is_tail_sentinel() && !node_b->is_tail_sentinel() + ; node_a = node_a->next, node_b = node_b->next) { + ir_variable *a = (ir_variable *) node_a; + ir_variable *b = (ir_variable *) node_b; /* 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; + return (node_a->is_tail_sentinel() == node_b->is_tail_sentinel()); } ir_function_signature * -ir_function::exact_matching_signature(exec_list *actual_parameters) +ir_function::exact_matching_signature(const exec_list *actual_parameters) { foreach_iter(exec_list_iterator, iter, signatures) { ir_function_signature *const sig =