[Mesa-dev] [PATCH 2/2] glsl: struct constructors/initializers only allow implicit conversions

Timothy Arceri timothy.arceri at collabora.com
Mon Aug 1 00:01:46 UTC 2016


On Sun, 2016-07-31 at 18:43 +0300, Andres Gomez wrote:
> When an argument for a structure constructor or initializer doesn't
> match the expected type, only Section 4.1.10 “Implicit Conversions”
> are allowed to try to match that expected type.
> 
> From page 32 (page 38 of the PDF) of the GLSL 1.20 spec:
> 
>   " The arguments to the constructor will be used to set the
> structure's
>     fields, in order, using one argument per field. Each argument
> must
>     be the same type as the field it sets, or be a type that can be
>     converted to the field's type according to Section 4.1.10
> “Implicit
>     Conversions.”"
> 
> From page 35 (page 41 of the PDF) of the GLSL 4.20 spec:
> 
>   " In all cases, the innermost initializer (i.e., not a list of
>     initializers enclosed in curly braces) applied to an object must
>     have the same type as the object being initialized or be a type
> that
>     can be converted to the object's type according to section 4.1.10
>     "Implicit Conversions". In the latter case, an implicit
> conversion
>     will be done on the initializer before the assignment is done."
> 
> Fixes GL44-CTS.shading_language_420pack.initializer_list_negative
> 
> Signed-off-by: Andres Gomez <agomez at igalia.com>
> ---
>  src/compiler/glsl/ast_function.cpp | 62
> ++++++++++++++++++++++++++++----------
>  1 file changed, 46 insertions(+), 16 deletions(-)
> 
> diff --git a/src/compiler/glsl/ast_function.cpp
> b/src/compiler/glsl/ast_function.cpp
> index 9dcec50..9b09cb6 100644
> --- a/src/compiler/glsl/ast_function.cpp
> +++ b/src/compiler/glsl/ast_function.cpp
> @@ -31,10 +31,6 @@
>  static ir_rvalue *
>  convert_component(ir_rvalue *src, const glsl_type *desired_type);
>  
> -bool
> -apply_implicit_conversion(const glsl_type *to, ir_rvalue * &from,
> -                          struct _mesa_glsl_parse_state *state);
> -

I'd put this in a third patch when you remove this and
make apply_implicit_conversion() static.

>  static unsigned
>  process_parameters(exec_list *instructions, exec_list
> *actual_parameters,
>  		   exec_list *parameters,
> @@ -1703,6 +1699,23 @@ process_record_constructor(exec_list
> *instructions,
>                             struct _mesa_glsl_parse_state *state)
>  {
>     void *ctx = state;
> +   /* From page 32 (page 38 of the PDF) of the GLSL 1.20 spec:
> +    *
> +    *    "The arguments to the constructor will be used to set the
> structure's
> +    *     fields, in order, using one argument per field. Each
> argument must
> +    *     be the same type as the field it sets, or be a type that
> can be
> +    *     converted to the field's type according to Section 4.1.10
> “Implicit
> +    *     Conversions.”"
> +    *
> +    * From page 35 (page 41 of the PDF) of the GLSL 4.20 spec:
> +    *
> +    *    "In all cases, the innermost initializer (i.e., not a list
> of
> +    *     initializers enclosed in curly braces) applied to an
> object must
> +    *     have the same type as the object being initialized or be a
> type that
> +    *     can be converted to the object's type according to section
> 4.1.10
> +    *     "Implicit Conversions". In the latter case, an implicit
> conversion
> +    *     will be done on the initializer before the assignment is
> done."
> +    */
>     exec_list actual_parameters;
>  
>     process_parameters(instructions, &actual_parameters,
> @@ -1710,7 +1723,7 @@ process_record_constructor(exec_list
> *instructions,
>  
>     exec_node *node = actual_parameters.get_head_raw();
>     for (unsigned i = 0; i < constructor_type->length; i++) {
> -      ir_rvalue *ir = (ir_rvalue *) node;
> +      ir_rvalue *result = (ir_rvalue *) node;

Maybe its just me but I find this naming really confusing when trying
to read the following code, I'd just leave it as ir.

>  
>        if (node->is_tail_sentinel()) {
>           _mesa_glsl_error(loc, state,
> @@ -1719,18 +1732,35 @@ process_record_constructor(exec_list
> *instructions,
>           return ir_rvalue::error_value(ctx);
>        }
>  
> -      if (apply_implicit_conversion(constructor_type-
> >fields.structure[i].type,
> -                                 ir, state)) {
> -         node->replace_with(ir);
> -      } else {
> -         _mesa_glsl_error(loc, state,
> -                          "parameter type mismatch in constructor
> for `%s.%s' "
> -                          "(%s vs %s)",
> -                          constructor_type->name,
> -                          constructor_type-
> >fields.structure[i].name,
> -                          ir->type->name,
> -                          constructor_type-
> >fields.structure[i].type->name);
> +      const glsl_base_type element_base_type =
> +         constructor_type->fields.structure[i].type->base_type;
> +
> +      /* Apply implicit conversions (not the scalar constructor
> rules!). See
> +       * the spec quote above. */

*/ should be on the next line

> +      if (element_base_type != result->type->base_type) {
> +         const glsl_type *desired_type =
> +            glsl_type::get_instance(element_base_type,
> +                                    result->type->vector_elements,
> +                                    result->type->matrix_columns);
> +
> +	 if (result->type->can_implicitly_convert_to(desired_type,
> state)) {
> +	    /* Even though convert_component() implements the
> constructor
> +	     * conversion rules (not the implicit conversion rules),
> its safe
> +	     * to use it here because we already checked that the
> implicit
> +	     * conversion is legal.
> +	     */
> +	    result = convert_component(result, desired_type);
> +	 }

You are adding a bunch of tabs above please remove them. It would be
nice if you could add a forth patch to the series that removes the
remain tabs in this file since there are not many remaining.

> +      }
> +
> +      if (result->type != constructor_type-
> >fields.structure[i].type) {
> +	 _mesa_glsl_error(loc, state, "type error in array
> constructor: "
> +			  "expected: %s, found %s",
> +			  constructor_type-
> >fields.structure[i].type->name,
> +			  result->type->name);
>           return ir_rvalue::error_value(ctx);
> +      } else {
> +         node->replace_with(result);
>        }

This if-else should be inside the previous if.

 The node->replace_with(result); should be after
 result = convert_component(result, desired_type);

Otherwise you are replacing the node with itself.

The error message can be added as an else to if (result->type-
>can_implicitly_convert_to())

>  
>        node = node->next;

I'm still not entirely sure I understand why this patch is different
from using apply_implicit_conversion() can you explain to me why
apply_implicit_conversion() does not match the rules correctly? Thanks
:)


More information about the mesa-dev mailing list