Mesa (7.9): glsl: Finish out the reduce/reduce error fixes

Ian Romanick idr at kemper.freedesktop.org
Tue Mar 1 00:04:40 UTC 2011


Module: Mesa
Branch: 7.9
Commit: 808ba96f3ed6f05abcd8f0a6decf6a66a37a0b85
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=808ba96f3ed6f05abcd8f0a6decf6a66a37a0b85

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Thu Jan 27 17:52:19 2011 -0800

glsl: Finish out the reduce/reduce error fixes

Track variables, functions, and types during parsing.  Use this
information in the lexer to return the currect "type" for identifiers.

Change the handling of structure constructors.  They will now show up
in the AST as constructors (instead of plain function calls).

Fixes piglit tests constructor-18.vert, constructor-19.vert, and
constructor-20.vert.  Also fixes bugzilla #29926.

NOTE: This is a candidate for the 7.9 and 7.10 branches.

(cherry picked from commit 884215894493bdbc55abd567c121c9df06ae3bc7)

---

 src/glsl/ast_function.cpp |  109 +++++++++++++++++++++++++--------------------
 src/glsl/glsl_lexer.lpp   |   17 ++++++-
 src/glsl/glsl_parser.ypp  |   41 ++++++++++++++---
 3 files changed, 109 insertions(+), 58 deletions(-)

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 9cf6b7d..c99512c 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -980,6 +980,16 @@ ast_function_expression::hir(exec_list *instructions,
 
       const glsl_type *const constructor_type = type->glsl_type(& name, state);
 
+      /* constructor_type can be NULL if a variable with the same name as the
+       * structure has come into scope.
+       */
+      if (constructor_type == NULL) {
+	 _mesa_glsl_error(& loc, state, "unknown type `%s' (structure name "
+			  "may be shadowed by a variable with the same name)",
+			  type->type_name);
+	 return ir_call::get_error_instruction(ctx);
+      }
+
 
       /* Constructors for samplers are illegal.
        */
@@ -1009,6 +1019,57 @@ ast_function_expression::hir(exec_list *instructions,
        * correct order.  These constructors follow essentially the same type
        * matching rules as functions.
        */
+      if (constructor_type->is_record()) {
+	 exec_list actual_parameters;
+
+	 process_parameters(instructions, &actual_parameters,
+			    &this->expressions, state);
+
+	 exec_node *node = actual_parameters.head;
+	 for (unsigned i = 0; i < constructor_type->length; i++) {
+	    ir_rvalue *ir = (ir_rvalue *) node;
+
+	    if (node->is_tail_sentinel()) {
+	       _mesa_glsl_error(&loc, state,
+				"insufficient parameters to constructor "
+				"for `%s'",
+				constructor_type->name);
+	       return ir_call::get_error_instruction(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);
+	       return ir_call::get_error_instruction(ctx);;
+	    }
+
+	    node = node->next;
+	 }
+
+	 if (!node->is_tail_sentinel()) {
+	    _mesa_glsl_error(&loc, state, "too many parameters in constructor "
+			     "for `%s'", constructor_type->name);
+	    return ir_call::get_error_instruction(ctx);
+	 }
+
+	 ir_rvalue *const constant =
+	    constant_record_constructor(constructor_type, &actual_parameters,
+					state);
+
+	 return (constant != NULL)
+	    ? constant
+	    : emit_inline_record_constructor(constructor_type, instructions,
+					     &actual_parameters, state);
+      }
+
       if (!constructor_type->is_numeric() && !constructor_type->is_boolean())
 	 return ir_call::get_error_instruction(ctx);
 
@@ -1184,54 +1245,6 @@ ast_function_expression::hir(exec_list *instructions,
       process_parameters(instructions, &actual_parameters, &this->expressions,
 			 state);
 
-      const glsl_type *const type =
-	 state->symbols->get_type(id->primary_expression.identifier);
-
-      if ((type != NULL) && type->is_record()) {
-	 exec_node *node = actual_parameters.head;
-	 for (unsigned i = 0; i < type->length; i++) {
-	    ir_rvalue *ir = (ir_rvalue *) node;
-
-	    if (node->is_tail_sentinel()) {
-	       _mesa_glsl_error(&loc, state,
-				"insufficient parameters to constructor "
-				"for `%s'",
-				type->name);
-	       return ir_call::get_error_instruction(ctx);
-	    }
-
-	    if (apply_implicit_conversion(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)",
-				type->name,
-				type->fields.structure[i].name,
-				ir->type->name,
-				type->fields.structure[i].type->name);
-	       return ir_call::get_error_instruction(ctx);;
-	    }
-
-	    node = node->next;
-	 }
-
-	 if (!node->is_tail_sentinel()) {
-	    _mesa_glsl_error(&loc, state, "too many parameters in constructor "
-			     "for `%s'", type->name);
-	    return ir_call::get_error_instruction(ctx);
-	 }
-
-	 ir_rvalue *const constant =
-	    constant_record_constructor(type, &actual_parameters, state);
-
-	 return (constant != NULL)
-	    ? constant
-	    : emit_inline_record_constructor(type, instructions,
-					     &actual_parameters, state);
-      }
-
       return match_function_by_name(instructions, 
 				    id->primary_expression.identifier, & loc,
 				    &actual_parameters, state);
diff --git a/src/glsl/glsl_lexer.lpp b/src/glsl/glsl_lexer.lpp
index 91a33a6..02d4528 100644
--- a/src/glsl/glsl_lexer.lpp
+++ b/src/glsl/glsl_lexer.lpp
@@ -27,6 +27,8 @@
 #include "glsl_parser_extras.h"
 #include "glsl_parser.h"
 
+static int classify_identifier(struct _mesa_glsl_parse_state *, const char *);
+
 #define YY_USER_ACTION						\
    do {								\
       yylloc->source = 0;					\
@@ -43,7 +45,7 @@
 	 return token;						 \
       } else {							 \
 	 yylval->identifier = strdup(yytext);			 \
-	 return IDENTIFIER;					 \
+	 return classify_identifier(yyextra, yytext);		 \
       }								 \
    } while (0)
 
@@ -383,13 +385,24 @@ row_major	TOKEN_OR_IDENTIFIER(130, ROW_MAJOR);
 			    struct _mesa_glsl_parse_state *state = yyextra;
 			    void *ctx = state;	
 			    yylval->identifier = ralloc_strdup(ctx, yytext);
-			    return IDENTIFIER;
+			    return classify_identifier(state, yytext);
 			}
 
 .			{ return yytext[0]; }
 
 %%
 
+int
+classify_identifier(struct _mesa_glsl_parse_state *state, const char *name)
+{
+   if (state->symbols->get_variable(name) || state->symbols->get_function(name))
+      return IDENTIFIER;
+   else if (state->symbols->get_type(name))
+      return TYPE_IDENTIFIER;
+   else
+      return NEW_IDENTIFIER;
+}
+
 void
 _mesa_glsl_lexer_ctor(struct _mesa_glsl_parse_state *state, const char *string)
 {
diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp
index 72a7234..041a49f 100644
--- a/src/glsl/glsl_parser.ypp
+++ b/src/glsl/glsl_parser.ypp
@@ -221,6 +221,11 @@ translation_unit:
 	   _mesa_glsl_initialize_types(state);
 	}
 	external_declaration_list
+	{
+	   delete state->symbols;
+	   state->symbols = new(ralloc_parent(state)) glsl_symbol_table;
+	   _mesa_glsl_initialize_types(state);
+	}
 	;
 
 version_statement:
@@ -761,6 +766,7 @@ constant_expression:
 declaration:
 	function_prototype ';'
 	{
+	   state->symbols->pop_scope();
 	   $$ = $1;
 	}
 	| init_declarator_list ';'
@@ -805,6 +811,10 @@ function_header:
 	   $$->set_location(yylloc);
 	   $$->return_type = $1;
 	   $$->identifier = $2;
+
+	   state->symbols->add_function($$->identifier,
+					new(state) ir_function($2));
+	   state->symbols->push_scope();
 	}
 	;
 
@@ -889,6 +899,7 @@ init_declarator_list:
 
 	   $$ = $1;
 	   $$->declarations.push_tail(&decl->link);
+	   state->symbols->add_variable($3, new(state) ir_variable(NULL, $3, ir_var_auto));
 	}
 	| init_declarator_list ',' any_identifier '[' ']'
 	{
@@ -898,6 +909,7 @@ init_declarator_list:
 
 	   $$ = $1;
 	   $$->declarations.push_tail(&decl->link);
+	   state->symbols->add_variable($3, new(state) ir_variable(NULL, $3, ir_var_auto));
 	}
 	| init_declarator_list ',' any_identifier '[' constant_expression ']'
 	{
@@ -907,6 +919,7 @@ init_declarator_list:
 
 	   $$ = $1;
 	   $$->declarations.push_tail(&decl->link);
+	   state->symbols->add_variable($3, new(state) ir_variable(NULL, $3, ir_var_auto));
 	}
 	| init_declarator_list ',' any_identifier '[' ']' '=' initializer
 	{
@@ -916,6 +929,7 @@ init_declarator_list:
 
 	   $$ = $1;
 	   $$->declarations.push_tail(&decl->link);
+	   state->symbols->add_variable($3, new(state) ir_variable(NULL, $3, ir_var_auto));
 	}
 	| init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer
 	{
@@ -925,6 +939,7 @@ init_declarator_list:
 
 	   $$ = $1;
 	   $$->declarations.push_tail(&decl->link);
+	   state->symbols->add_variable($3, new(state) ir_variable(NULL, $3, ir_var_auto));
 	}
 	| init_declarator_list ',' any_identifier '=' initializer
 	{
@@ -934,6 +949,7 @@ init_declarator_list:
 
 	   $$ = $1;
 	   $$->declarations.push_tail(&decl->link);
+	   state->symbols->add_variable($3, new(state) ir_variable(NULL, $3, ir_var_auto));
 	}
 	;
 
@@ -1004,7 +1020,7 @@ single_declaration:
 	   $$->set_location(yylloc);
 	   $$->declarations.push_tail(&decl->link);
 	}
-	| INVARIANT IDENTIFIER // Vertex only.
+	| INVARIANT variable_identifier // Vertex only.
 	{
 	   void *ctx = state;
 	   ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL);
@@ -1056,7 +1072,7 @@ layout_qualifier_id_list:
 	;
 
 layout_qualifier_id:
-	IDENTIFIER
+	any_identifier
 	{
 	   $$.i = 0;
 
@@ -1261,11 +1277,12 @@ precision_qualifier:
 	;
 
 struct_specifier:
-	STRUCT IDENTIFIER '{' struct_declaration_list '}'
+	STRUCT any_identifier '{' struct_declaration_list '}'
 	{
 	   void *ctx = state;
 	   $$ = new(ctx) ast_struct_specifier($2, $4);
 	   $$->set_location(yylloc);
+	   state->symbols->add_type($2, glsl_type::void_type);
 	}
 	| STRUCT '{' struct_declaration_list '}'
 	{
@@ -1317,13 +1334,14 @@ struct_declarator_list:
 	;
 
 struct_declarator:
-	IDENTIFIER
+	any_identifier
 	{
 	   void *ctx = state;
 	   $$ = new(ctx) ast_declaration($1, false, NULL, NULL);
 	   $$->set_location(yylloc);
+	   state->symbols->add_variable($1, new(state) ir_variable(NULL, $1, ir_var_auto));
 	}
-	| IDENTIFIER '[' constant_expression ']'
+	| any_identifier '[' constant_expression ']'
 	{
 	   void *ctx = state;
 	   $$ = new(ctx) ast_declaration($1, true, $3, NULL);
@@ -1363,11 +1381,16 @@ compound_statement:
 	   $$ = new(ctx) ast_compound_statement(true, NULL);
 	   $$->set_location(yylloc);
 	}
-	| '{' statement_list '}'
+	| '{'
+	{
+	   state->symbols->push_scope();
+	}
+	statement_list '}'
 	{
 	   void *ctx = state;
-	   $$ = new(ctx) ast_compound_statement(true, $2);
+	   $$ = new(ctx) ast_compound_statement(true, $3);
 	   $$->set_location(yylloc);
+	   state->symbols->pop_scope();
 	}
 	;
 
@@ -1455,7 +1478,7 @@ condition:
 	{
 	   $$ = (ast_node *) $1;
 	}
-	| fully_specified_type IDENTIFIER '=' initializer
+	| fully_specified_type any_identifier '=' initializer
 	{
 	   void *ctx = state;
 	   ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, $4);
@@ -1575,5 +1598,7 @@ function_definition:
 	   $$->set_location(yylloc);
 	   $$->prototype = $1;
 	   $$->body = $2;
+
+	   state->symbols->pop_scope();
 	}
 	;




More information about the mesa-commit mailing list