[Mesa-dev] [PATCH 2/5] glsl: Fix implicit conversions in non-constructor function calls

Kenneth Graunke kenneth at whitecape.org
Fri Jul 29 14:08:57 PDT 2011


On 07/27/2011 10:55 PM, Chad Versace wrote:
> Context
> -------
> In ast_function_expression::hir(), parameter_lists_match() checks if the
> function call's actual parameter list matches the signature's parameter
> list, where the match may require implicit conversion of some arguments.
> To check if an implicit conversion exists between individual arguments,
> type_compare() is used.
> 
> Problems
> --------
> type_compare() allowed the following illegal implicit conversions:
>     bool -> float
>     bvecN -> vecN
> 
>     int -> uint
>     ivecN -> uvecN
> 
>     uint -> int
>     uvecN -> ivecN
> 
> Change
> ------
> type_compare() is buggy, so replace it with glsl_type::can_be_implicitly_converted_to().
> This comprises a rewrite of parameter_lists_match().
> 
> Fixes Piglit spec/glsl-1.20/compiler/built-in-functions/outerProduct-bvec*.vert
> 
> Note: This is a candidate for the 7.10 and 7.11 branches.
> CC: Ian Romanick <ian.d.romanick at intel.com>
> CC: Kenneth Graunke <kenneth at whitecape.org>
> Signed-off-by: Chad Versace <chad at chad-versace.us>
> ---
>  src/glsl/glsl_types.cpp  |   23 +++----------------
>  src/glsl/ir_function.cpp |   52 +++++++++++++++++++++++++++++----------------
>  2 files changed, 37 insertions(+), 38 deletions(-)
> 
> diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
> index 9cfdcab..3b97aa9 100644
> --- a/src/glsl/glsl_types.cpp
> +++ b/src/glsl/glsl_types.cpp
> @@ -531,25 +531,10 @@ glsl_type::can_implicitly_convert_to(const glsl_type *desired) const
>        return true;
>  
>     /* There is no conversion among matrix types. */
> -   if (this->matrix_columns != 1 || desired->matrix_columns != 1)
> +   if (this->matrix_columns > 1 || desired->matrix_columns > 1)
>        return false;
>  
> -   switch (desired->base_type) {
> -   case GLSL_TYPE_UINT:
> -   case GLSL_TYPE_INT:
> -   case GLSL_TYPE_BOOL:
> -   case GLSL_TYPE_SAMPLER:
> -   case GLSL_TYPE_STRUCT:
> -   case GLSL_TYPE_VOID:
> -   case GLSL_TYPE_ERROR:
> -      return false;
> -
> -   case GLSL_TYPE_FLOAT:
> -      return this->is_integer()
> -	     && this->vector_elements == desired->vector_elements;
> -
> -   default:
> -      assert(0);
> -      return false;
> -   }
> +   return desired->is_float()
> +          && this->is_integer()
> +          && this->vector_elements == desired->vector_elements;
>  }

I think you meant to merge this into the previous patch.  Please do so.

> diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp
> index 0f2f1a0..56d50a8 100644
> --- a/src/glsl/ir_function.cpp
> +++ b/src/glsl/ir_function.cpp
> @@ -85,12 +85,25 @@ type_compare(const glsl_type *a, const glsl_type *b)
>  }
>  
>  
> +/**
> + * \brief Check if two parameter lists match.
> + *
> + * \param list_a Parameters of the function definition.
> + * \param list_b Actual parameters passed to the function.
> + * \return If an exact match, return 0.
> + *         If an inexact match requiring implicit conversion, return 1.
> + *         If not a match, return -1.
> + * \see matching_signature()
> + */
>  static int
>  parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
>  {
>     const exec_node *node_a = list_a->head;
>     const exec_node *node_b = list_b->head;
> -   int total_score = 0;
> +
> +   /* This is set to true if there is an inexact match requiring an implicit
> +    * conversion. */
> +   bool inexact_match = false;
>  
>     for (/* empty */
>  	; !node_a->is_tail_sentinel()
> @@ -106,12 +119,11 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
>        const ir_variable *const param = (ir_variable *) node_a;
>        const ir_instruction *const actual = (ir_instruction *) 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:
> @@ -125,29 +137,28 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
>  
>        case ir_var_const_in:
>        case ir_var_in:
> -	 score = type_compare(param->type, actual->type);
> -	 break;
> +	 if (actual->type->can_implicitly_convert_to(param->type))
> +	    continue;
> +	 else
> +	    return -1;

I think this would be easier to read in the more conventional form:

+	 if (!actual->type->can_implicitly_convert_to(param->type))
+	    return -1;
+	 break;

>        case ir_var_out:
> -	 score = type_compare(actual->type, param->type);
> -	 break;
> +	 if (param->type->can_implicitly_convert_to(actual->type))
> +	    continue;
> +	 else
> +	    return -1;

Ditto.

>        case ir_var_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;
> +	 return -1;
>  
>        default:
>  	 assert(false);
> -      }
> -
> -      if (score < 0)
>  	 return -1;
> -
> -      total_score += score;
> +      }
>     }
>  
>     /* If all of the parameters from the other parameter list have been
> @@ -157,7 +168,10 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
>     if (!node_b->is_tail_sentinel())
>        return -1;
>  
> -   return total_score;
> +   if (inexact_match)
> +      return 1;
> +   else
> +      return 0;
>  }

Otherwise, looks good to me.


More information about the mesa-dev mailing list