diff options
Diffstat (limited to 'src/glsl/glsl_parser.ypp')
-rw-r--r-- | src/glsl/glsl_parser.ypp | 226 |
1 files changed, 177 insertions, 49 deletions
diff --git a/src/glsl/glsl_parser.ypp b/src/glsl/glsl_parser.ypp index 0df1e480ce3..ed18179beb7 100644 --- a/src/glsl/glsl_parser.ypp +++ b/src/glsl/glsl_parser.ypp @@ -54,10 +54,7 @@ float real; char *identifier; - union { - struct ast_type_qualifier q; - unsigned i; - } type_qualifier; + struct ast_type_qualifier type_qualifier; ast_node *node; ast_type_specifier *type_specifier; @@ -139,7 +136,7 @@ %type <type_qualifier> type_qualifier %type <type_qualifier> storage_qualifier %type <type_qualifier> interpolation_qualifier -%type <type_qualifier> opt_layout_qualifier layout_qualifier +%type <type_qualifier> layout_qualifier %type <type_qualifier> layout_qualifier_id_list layout_qualifier_id %type <type_specifier> type_specifier %type <type_specifier> type_specifier_no_prec @@ -760,25 +757,25 @@ parameter_declarator: parameter_declaration: parameter_type_qualifier parameter_qualifier parameter_declarator { - $1.i |= $2.i; + $1.flags.i |= $2.flags.i; $$ = $3; - $$->type->qualifier = $1.q; + $$->type->qualifier = $1; } | parameter_qualifier parameter_declarator { $$ = $2; - $$->type->qualifier = $1.q; + $$->type->qualifier = $1; } | parameter_type_qualifier parameter_qualifier parameter_type_specifier { void *ctx = state; - $1.i |= $2.i; + $1.flags.i |= $2.flags.i; $$ = new(ctx) ast_parameter_declarator(); $$->set_location(yylloc); $$->type = new(ctx) ast_fully_specified_type(); - $$->type->qualifier = $1.q; + $$->type->qualifier = $1; $$->type->specifier = $3; } | parameter_qualifier parameter_type_specifier @@ -787,16 +784,32 @@ parameter_declaration: $$ = new(ctx) ast_parameter_declarator(); $$->set_location(yylloc); $$->type = new(ctx) ast_fully_specified_type(); - $$->type->qualifier = $1.q; + $$->type->qualifier = $1; $$->type->specifier = $2; } ; parameter_qualifier: - /* empty */ { $$.i = 0; } - | IN_TOK { $$.i = 0; $$.q.in = 1; } - | OUT_TOK { $$.i = 0; $$.q.out = 1; } - | INOUT_TOK { $$.i = 0; $$.q.in = 1; $$.q.out = 1; } + /* empty */ + { + memset(& $$, 0, sizeof($$)); + } + | IN_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.in = 1; + } + | OUT_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.out = 1; + } + | INOUT_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.in = 1; + $$.flags.q.out = 1; + } ; parameter_type_specifier: @@ -954,16 +967,11 @@ fully_specified_type: void *ctx = state; $$ = new(ctx) ast_fully_specified_type(); $$->set_location(yylloc); - $$->qualifier = $1.q; + $$->qualifier = $1; $$->specifier = $2; } ; -opt_layout_qualifier: - { $$.i = 0; } - | layout_qualifier - ; - layout_qualifier: LAYOUT_TOK '(' layout_qualifier_id_list ')' { @@ -975,77 +983,197 @@ layout_qualifier_id_list: layout_qualifier_id | layout_qualifier_id_list ',' layout_qualifier_id { - $$.i = $1.i | $3.i; + if (($1.flags.i & $3.flags.i) != 0) { + _mesa_glsl_error(& @3, state, + "duplicate layout qualifiers used\n"); + YYERROR; + } + + $$.flags.i = $1.flags.i | $3.flags.i; + + if ($1.flags.q.explicit_location) + $$.location = $1.location; + + if ($3.flags.q.explicit_location) + $$.location = $3.location; } ; layout_qualifier_id: IDENTIFIER { - $$.i = 0; + bool got_one = false; - if (state->ARB_fragment_coord_conventions_enable) { - bool got_one = false; + memset(& $$, 0, sizeof($$)); + if (state->ARB_fragment_coord_conventions_enable) { if (strcmp($1, "origin_upper_left") == 0) { got_one = true; - $$.q.origin_upper_left = 1; + $$.flags.q.origin_upper_left = 1; } else if (strcmp($1, "pixel_center_integer") == 0) { got_one = true; - $$.q.pixel_center_integer = 1; + $$.flags.q.pixel_center_integer = 1; } + } - if (state->ARB_fragment_coord_conventions_warn && got_one) { - _mesa_glsl_warning(& @1, state, - "GL_ARB_fragment_coord_conventions layout " - "identifier `%s' used\n", $1); + /* If the identifier didn't match any known layout identifiers, + * emit an error. + */ + if (!got_one) { + _mesa_glsl_error(& @1, state, "unrecognized layout identifier " + "`%s'\n", $1); + YYERROR; + } else if (state->ARB_fragment_coord_conventions_warn) { + _mesa_glsl_warning(& @1, state, + "GL_ARB_fragment_coord_conventions layout " + "identifier `%s' used\n", $1); + } + } + | IDENTIFIER '=' INTCONSTANT + { + bool got_one = false; + + memset(& $$, 0, sizeof($$)); + + if (state->ARB_explicit_attrib_location_enable) { + /* FINISHME: Handle 'index' once GL_ARB_blend_func_exteneded and + * FINISHME: GLSL 1.30 (or later) are supported. + */ + if (strcmp("location", $1) == 0) { + got_one = true; + + $$.flags.q.explicit_location = 1; + + if ($3 >= 0) { + $$.location = $3; + } else { + _mesa_glsl_error(& @3, state, + "invalid location %d specified\n", $3); + YYERROR; + } } } /* If the identifier didn't match any known layout identifiers, * emit an error. */ - if ($$.i == 0) { + if (!got_one) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'\n", $1); YYERROR; + } else if (state->ARB_explicit_attrib_location_warn) { + _mesa_glsl_warning(& @1, state, + "GL_ARB_explicit_attrib_location layout " + "identifier `%s' used\n", $1); } } ; interpolation_qualifier: - SMOOTH { $$.i = 0; $$.q.smooth = 1; } - | FLAT { $$.i = 0; $$.q.flat = 1; } - | NOPERSPECTIVE { $$.i = 0; $$.q.noperspective = 1; } + SMOOTH + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.smooth = 1; + } + | FLAT + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.flat = 1; + } + | NOPERSPECTIVE + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.noperspective = 1; + } ; parameter_type_qualifier: - CONST_TOK { $$.i = 0; $$.q.constant = 1; } + CONST_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.constant = 1; + } ; type_qualifier: storage_qualifier - | interpolation_qualifier type_qualifier + | layout_qualifier + | layout_qualifier storage_qualifier { - $$.i = $1.i | $2.i; + $$ = $1; + $$.flags.i |= $2.flags.i; } - | INVARIANT type_qualifier + | interpolation_qualifier + | interpolation_qualifier storage_qualifier + { + $$ = $1; + $$.flags.i |= $2.flags.i; + } + | INVARIANT storage_qualifier + { + $$ = $2; + $$.flags.q.invariant = 1; + } + | INVARIANT interpolation_qualifier storage_qualifier { $$ = $2; - $$.q.invariant = 1; + $$.flags.i |= $3.flags.i; + $$.flags.q.invariant = 1; + } + | INVARIANT + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.invariant = 1; } ; storage_qualifier: - CONST_TOK { $$.i = 0; $$.q.constant = 1; } - | ATTRIBUTE { $$.i = 0; $$.q.attribute = 1; } - | opt_layout_qualifier VARYING { $$.i = $1.i; $$.q.varying = 1; } - | CENTROID VARYING { $$.i = 0; $$.q.centroid = 1; $$.q.varying = 1; } - | opt_layout_qualifier IN_TOK { $$.i = 0; $$.q.in = 1; } - | OUT_TOK { $$.i = 0; $$.q.out = 1; } - | CENTROID IN_TOK { $$.i = 0; $$.q.centroid = 1; $$.q.in = 1; } - | CENTROID OUT_TOK { $$.i = 0; $$.q.centroid = 1; $$.q.out = 1; } - | UNIFORM { $$.i = 0; $$.q.uniform = 1; } + CONST_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.constant = 1; + } + | ATTRIBUTE + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.attribute = 1; + } + | VARYING + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.varying = 1; + } + | CENTROID VARYING + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.centroid = 1; + $$.flags.q.varying = 1; + } + | IN_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.in = 1; + } + | OUT_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.out = 1; + } + | CENTROID IN_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.centroid = 1; $$.flags.q.in = 1; + } + | CENTROID OUT_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.centroid = 1; $$.flags.q.out = 1; + } + | UNIFORM + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.uniform = 1; + } ; type_specifier: |