diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/glsl/ast_function.cpp | 109 | ||||
-rw-r--r-- | src/glsl/glsl_lexer.lpp | 17 | ||||
-rw-r--r-- | src/glsl/glsl_parser.ypp | 42 |
3 files changed, 109 insertions, 59 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp index 7611617df7e..e5cb8733952 100644 --- a/src/glsl/ast_function.cpp +++ b/src/glsl/ast_function.cpp @@ -1017,6 +1017,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. */ @@ -1046,6 +1056,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); @@ -1221,54 +1282,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 d3d53ffb68e..e4c469f9e0a 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; \ @@ -62,7 +64,7 @@ return ERROR_TOK; \ } else { \ yylval->identifier = strdup(yytext); \ - return IDENTIFIER; \ + return classify_identifier(yyextra, yytext); \ } \ } while (0) @@ -419,13 +421,24 @@ row_major KEYWORD(130, 999, 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 dd23279aaae..2c0498ece7a 100644 --- a/src/glsl/glsl_parser.ypp +++ b/src/glsl/glsl_parser.ypp @@ -219,6 +219,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: @@ -759,6 +764,7 @@ constant_expression: declaration: function_prototype ';' { + state->symbols->pop_scope(); $$ = $1; } | init_declarator_list ';' @@ -803,6 +809,9 @@ function_header: $$->set_location(yylloc); $$->return_type = $1; $$->identifier = $2; + + state->symbols->add_function(new(state) ir_function($2)); + state->symbols->push_scope(); } ; @@ -903,6 +912,7 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } | init_declarator_list ',' any_identifier '[' ']' { @@ -912,6 +922,7 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } | init_declarator_list ',' any_identifier '[' constant_expression ']' { @@ -921,6 +932,7 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } | init_declarator_list ',' any_identifier '[' ']' '=' initializer { @@ -930,6 +942,7 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer { @@ -939,6 +952,7 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } | init_declarator_list ',' any_identifier '=' initializer { @@ -948,6 +962,7 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); } ; @@ -1018,7 +1033,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); @@ -1077,7 +1092,7 @@ layout_qualifier_id_list: ; layout_qualifier_id: - IDENTIFIER + any_identifier { bool got_one = false; @@ -1129,7 +1144,7 @@ layout_qualifier_id: YYERROR; } } - | IDENTIFIER '=' INTCONSTANT + | any_identifier '=' INTCONSTANT { bool got_one = false; @@ -1413,11 +1428,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 '}' { @@ -1469,13 +1485,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(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); @@ -1515,11 +1532,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(); } ; @@ -1607,7 +1629,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); @@ -1727,5 +1749,7 @@ function_definition: $$->set_location(yylloc); $$->prototype = $1; $$->body = $2; + + state->symbols->pop_scope(); } ; |