[Mesa-dev] [PATCH 3/5] glcpp: Allow arithmetic integer expressions in #line

Ian Romanick idr at freedesktop.org
Tue Jun 9 10:15:00 PDT 2015


On 03/11/2015 02:01 AM, Eduardo Lima Mitev wrote:
> From: Antia Puentes <apuentes at igalia.com>
> 
> From section 3.4 ("Preprocessor") of the GLSL ES 3.00 specification:
> "#line must have, after macro substitution, one of the following forms:
>    	#line line
>    	#line line source-string-number
> where line and source-string-number are constant integral expressions."
> 
> From section 4.3.3 ("Constant Expressions") of the same specification:
> "A constant integral expression is a constant expression that evaluates
> to a scalar signed or unsigned integer."

FFS.  I can't believe they have a test for this.  For what it's worth,
this makes the grammar non-LALR.  Not too long ago it came up for a vote
to remove this since it does not work on *ANY* desktop OpenGL
implementation.  While there was a majority vote to remove it, it was
not a large enough majority (by a single vote).  It is also a deviation
from C / C++ preprocessors.

Carl spent some time on this, and he couldn't find a way to make it work
without adding significant bison warnings or have it fail for some cases.

Does this patch work for:

#line 3 +3
#line 3 (+3)
#line 3 +3 3
#line 3 +3 (+3)
#line 3 +3 3 +3

It seems like there were a couple other cases, but I can't remember what
they were.  Perhaps Carl remembers.

> Fixes 4 dEQP tests:
>  * dEQP-GLES3.functional.shaders.preprocessor.builtin.line_expression_vertex
>  * dEQP-GLES3.functional.shaders.preprocessor.builtin.line_expression_fragment
>  * dEQP-GLES3.functional.shaders.preprocessor.builtin.line_and_file_expression_vertex
>  * dEQP-GLES3.functional.shaders.preprocessor.builtin.line_and_file_expression_fragment
> ---
>  src/glsl/glcpp/glcpp-parse.y | 91 ++++++++++++++++++++++++++++++++++++++------
>  1 file changed, 80 insertions(+), 11 deletions(-)
> 
> diff --git a/src/glsl/glcpp/glcpp-parse.y b/src/glsl/glcpp/glcpp-parse.y
> index c2f5223..0e96f53 100644
> --- a/src/glsl/glcpp/glcpp-parse.y
> +++ b/src/glsl/glcpp/glcpp-parse.y
> @@ -180,7 +180,7 @@ add_builtin_define(glcpp_parser_t *parser, const char *name, int value);
>           * (such as the <HASH> and <DEFINE> start conditions in the lexer). */
>  %token DEFINED ELIF_EXPANDED HASH_TOKEN DEFINE_TOKEN FUNC_IDENTIFIER OBJ_IDENTIFIER ELIF ELSE ENDIF ERROR_TOKEN IF IFDEF IFNDEF LINE PRAGMA UNDEF VERSION_TOKEN GARBAGE IDENTIFIER IF_EXPANDED INTEGER INTEGER_STRING LINE_EXPANDED NEWLINE OTHER PLACEHOLDER SPACE PLUS_PLUS MINUS_MINUS
>  %token PASTE
> -%type <ival> INTEGER operator SPACE integer_constant
> +%type <ival> INTEGER operator SPACE integer_constant constant_integral_expression
>  %type <expression_value> expression
>  %type <str> IDENTIFIER FUNC_IDENTIFIER OBJ_IDENTIFIER INTEGER_STRING OTHER ERROR_TOKEN PRAGMA
>  %type <string_list> identifier_list
> @@ -229,7 +229,7 @@ expanded_line:
>  			glcpp_error(& @1, parser, "undefined macro %s in expression (illegal in GLES)", $2.undefined_macro);
>  		_glcpp_parser_skip_stack_change_if (parser, & @1, "elif", $2.value);
>  	}
> -|	LINE_EXPANDED integer_constant NEWLINE {
> +|	LINE_EXPANDED constant_integral_expression NEWLINE {
>  		parser->has_new_line_number = 1;
>  		parser->new_line_number = $2;
>  		ralloc_asprintf_rewrite_tail (&parser->output,
> @@ -237,15 +237,53 @@ expanded_line:
>  					      "#line %" PRIiMAX "\n",
>  					      $2);
>  	}
> -|	LINE_EXPANDED integer_constant integer_constant NEWLINE {
> +|	LINE_EXPANDED constant_integral_expression SPACE constant_integral_expression NEWLINE {
>  		parser->has_new_line_number = 1;
>  		parser->new_line_number = $2;
>  		parser->has_new_source_number = 1;
> -		parser->new_source_number = $3;
> +		parser->new_source_number = $4;
>  		ralloc_asprintf_rewrite_tail (&parser->output,
>  					      &parser->output_length,
>  					      "#line %" PRIiMAX " %" PRIiMAX "\n",
> -					      $2, $3);
> +					      $2, $4);
> +	}
> +;
> +
> +constant_integral_expression:
> +        integer_constant {
> +                $$ = $1;
> +	}
> +|       constant_integral_expression '+' constant_integral_expression {
> +		$$ = $1 + $3;
> +	}
> +|       constant_integral_expression '-' constant_integral_expression {
> +		$$ = $1 - $3;
> +	}
> +|       constant_integral_expression '*' constant_integral_expression {
> +		$$ = $1 * $3;
> +	}
> +|       constant_integral_expression '/' constant_integral_expression {
> +                if ($3 == 0)
> +                        yyerror (&@1, parser,
> +                                 "division by 0 in preprocessor directive");
> +                else
> +		        $$ = $1 / $3;
> +        }
> +|       constant_integral_expression '%' constant_integral_expression {
> +                if ($3 == 0)
> +                        yyerror (&@1, parser,
> +                                 "zero modulus in preprocessor directive");
> +                else
> +                        $$ = $1 % $3;
> +	}
> +|	'+' constant_integral_expression %prec UNARY {
> +		$$ = $2;
> +	}
> +|	'-' constant_integral_expression %prec UNARY {
> +		$$ = -$2;
> +	}
> +|	'(' constant_integral_expression ')' {
> +		$$ = $2;
>  	}
>  ;
>  
> @@ -2275,14 +2313,45 @@ glcpp_parser_lex_from (glcpp_parser_t *parser, token_list_t *list)
>  	assert (parser->lex_from_list == NULL);
>  
>  	/* Copy list, eliminating any space tokens. */
> -	parser->lex_from_list = _token_list_create (parser);
>  
> -	for (node = list->head; node; node = node->next) {
> -		if (node->token->type == SPACE)
> -			continue;
> -		_token_list_append (parser->lex_from_list, node->token);
> -	}
> +	parser->lex_from_list = _token_list_create (parser);
>  
> +        /* If the list comes from a LINE_EXPANDED, do not remove the
> +         * SPACE tokens that act as parameter separator, i.e., SPACE tokens
> +         * inside parentheses will be removed, consecutive SPACE tokens
> +         * outside parentheses will be reduced to one.
> +         */
> +        if (list->head->token->type == LINE_EXPANDED) {
> +                int bracket_num = 0;
> +                bool separator = false;
> +
> +                _token_list_append (parser->lex_from_list, list->head->token);
> +
> +                for (node = list->head->next; node; node = node->next) {
> +                        token_t *token = node->token;
> +
> +                        if (token->type == '(')
> +                                bracket_num++;
> +                        if (token->type == ')')
> +                                bracket_num--;
> +
> +                        if (token->type == SPACE) {
> +                                if (bracket_num > 0 || separator)
> +                                        continue;
> +                                separator = true;
> +                        } else {
> +                                separator = false;
> +                        }
> +
> +                        _token_list_append (parser->lex_from_list, token);
> +                }
> +        } else {
> +                for (node = list->head; node; node = node->next) {
> +                        if (node->token->type == SPACE)
> +                                continue;
> +                        _token_list_append (parser->lex_from_list, node->token);
> +                }
> +        }
>  	ralloc_free (list);
>  
>  	parser->lex_from_node = parser->lex_from_list->head;
> 



More information about the mesa-dev mailing list