aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/glsl/glsl_parser.yy
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/glsl/glsl_parser.yy')
-rw-r--r--mesalib/src/glsl/glsl_parser.yy165
1 files changed, 134 insertions, 31 deletions
diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy
index 5ca8740c4..337337591 100644
--- a/mesalib/src/glsl/glsl_parser.yy
+++ b/mesalib/src/glsl/glsl_parser.yy
@@ -155,6 +155,7 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
%type <type_qualifier> interpolation_qualifier
%type <type_qualifier> layout_qualifier
%type <type_qualifier> layout_qualifier_id_list layout_qualifier_id
+%type <type_qualifier> uniform_block_layout_qualifier
%type <type_specifier> type_specifier
%type <type_specifier> type_specifier_no_prec
%type <type_specifier> type_specifier_nonarray
@@ -213,11 +214,14 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
%type <node> declaration
%type <node> declaration_statement
%type <node> jump_statement
+%type <node> uniform_block
%type <struct_specifier> struct_specifier
-%type <node> struct_declaration_list
+%type <declarator_list> struct_declaration_list
%type <declarator_list> struct_declaration
%type <declaration> struct_declarator
%type <declaration> struct_declarator_list
+%type <declarator_list> member_list
+%type <declarator_list> member_declaration
%type <node> selection_statement
%type <selection_rest_statement> selection_rest_statement
%type <node> switch_statement
@@ -800,6 +804,10 @@ declaration:
$3->is_precision_statement = true;
$$ = $3;
}
+ | uniform_block
+ {
+ $$ = $1;
+ }
;
function_prototype:
@@ -1100,13 +1108,8 @@ layout_qualifier_id_list:
YYERROR;
}
- $$.flags.i = $1.flags.i | $3.flags.i;
-
- if ($1.flags.q.explicit_location)
- $$.location = $1.location;
-
- if ($1.flags.q.explicit_index)
- $$.index = $1.index;
+ $$ = $1;
+ $$.flags.i |= $3.flags.i;
if ($3.flags.q.explicit_location)
$$.location = $3.location;
@@ -1119,21 +1122,17 @@ layout_qualifier_id_list:
layout_qualifier_id:
any_identifier
{
- bool got_one = false;
-
memset(& $$, 0, sizeof($$));
/* Layout qualifiers for ARB_fragment_coord_conventions. */
- if (!got_one && state->ARB_fragment_coord_conventions_enable) {
+ if (!$$.flags.i && state->ARB_fragment_coord_conventions_enable) {
if (strcmp($1, "origin_upper_left") == 0) {
- got_one = true;
$$.flags.q.origin_upper_left = 1;
} else if (strcmp($1, "pixel_center_integer") == 0) {
- got_one = true;
$$.flags.q.pixel_center_integer = 1;
}
- if (got_one && state->ARB_fragment_coord_conventions_warn) {
+ if ($$.flags.i && state->ARB_fragment_coord_conventions_warn) {
_mesa_glsl_warning(& @1, state,
"GL_ARB_fragment_coord_conventions layout "
"identifier `%s' used\n", $1);
@@ -1141,36 +1140,49 @@ layout_qualifier_id:
}
/* Layout qualifiers for AMD/ARB_conservative_depth. */
- if (!got_one &&
+ if (!$$.flags.i &&
(state->AMD_conservative_depth_enable ||
state->ARB_conservative_depth_enable)) {
if (strcmp($1, "depth_any") == 0) {
- got_one = true;
$$.flags.q.depth_any = 1;
} else if (strcmp($1, "depth_greater") == 0) {
- got_one = true;
$$.flags.q.depth_greater = 1;
} else if (strcmp($1, "depth_less") == 0) {
- got_one = true;
$$.flags.q.depth_less = 1;
} else if (strcmp($1, "depth_unchanged") == 0) {
- got_one = true;
$$.flags.q.depth_unchanged = 1;
}
- if (got_one && state->AMD_conservative_depth_warn) {
+ if ($$.flags.i && state->AMD_conservative_depth_warn) {
_mesa_glsl_warning(& @1, state,
"GL_AMD_conservative_depth "
"layout qualifier `%s' is used\n", $1);
}
- if (got_one && state->ARB_conservative_depth_warn) {
+ if ($$.flags.i && state->ARB_conservative_depth_warn) {
_mesa_glsl_warning(& @1, state,
"GL_ARB_conservative_depth "
"layout qualifier `%s' is used\n", $1);
}
}
- if (!got_one) {
+ /* See also uniform_block_layout_qualifier. */
+ if (!$$.flags.i && state->ARB_uniform_buffer_object_enable) {
+ if (strcmp($1, "std140") == 0) {
+ $$.flags.q.std140 = 1;
+ } else if (strcmp($1, "shared") == 0) {
+ $$.flags.q.shared = 1;
+ } else if (strcmp($1, "column_major") == 0) {
+ $$.flags.q.column_major = 1;
+ }
+
+ if ($$.flags.i && state->ARB_uniform_buffer_object_warn) {
+ _mesa_glsl_warning(& @1, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "layout qualifier `%s' is used\n", $1);
+ }
+ }
+
+ if (!$$.flags.i) {
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
"`%s'\n", $1);
YYERROR;
@@ -1178,8 +1190,6 @@ layout_qualifier_id:
}
| any_identifier '=' INTCONSTANT
{
- bool got_one = false;
-
memset(& $$, 0, sizeof($$));
if (state->ARB_explicit_attrib_location_enable) {
@@ -1187,8 +1197,6 @@ layout_qualifier_id:
* FINISHME: GLSL 1.30 (or later) are supported.
*/
if (strcmp("location", $1) == 0) {
- got_one = true;
-
$$.flags.q.explicit_location = 1;
if ($3 >= 0) {
@@ -1201,8 +1209,6 @@ layout_qualifier_id:
}
if (strcmp("index", $1) == 0) {
- got_one = true;
-
$$.flags.q.explicit_index = 1;
if ($3 >= 0) {
@@ -1218,7 +1224,7 @@ layout_qualifier_id:
/* If the identifier didn't match any known layout identifiers,
* emit an error.
*/
- if (!got_one) {
+ if (!$$.flags.i) {
_mesa_glsl_error(& @1, state, "unrecognized layout identifier "
"`%s'\n", $1);
YYERROR;
@@ -1228,6 +1234,38 @@ layout_qualifier_id:
"identifier `%s' used\n", $1);
}
}
+ | uniform_block_layout_qualifier
+ {
+ $$ = $1;
+ /* Layout qualifiers for ARB_uniform_buffer_object. */
+ if (!state->ARB_uniform_buffer_object_enable) {
+ _mesa_glsl_error(& @1, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "layout qualifier `%s' is used\n", $1);
+ } else if (state->ARB_uniform_buffer_object_warn) {
+ _mesa_glsl_warning(& @1, state,
+ "#version 140 / GL_ARB_uniform_buffer_object "
+ "layout qualifier `%s' is used\n", $1);
+ }
+ }
+ ;
+
+/* This is a separate language rule because we parse these as tokens
+ * (due to them being reserved keywords) instead of identifiers like
+ * most qualifiers. See the any_identifier path of
+ * layout_qualifier_id for the others.
+ */
+uniform_block_layout_qualifier:
+ ROW_MAJOR
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.row_major = 1;
+ }
+ | PACKED_TOK
+ {
+ memset(& $$, 0, sizeof($$));
+ $$.flags.q.packed = 1;
+ }
;
interpolation_qualifier:
@@ -1498,12 +1536,12 @@ struct_specifier:
struct_declaration_list:
struct_declaration
{
- $$ = (ast_node *) $1;
+ $$ = $1;
$1->link.self_link();
}
| struct_declaration_list struct_declaration
{
- $$ = (ast_node *) $1;
+ $$ = $1;
$$->link.insert_before(& $2->link);
}
;
@@ -1881,3 +1919,68 @@ function_definition:
state->symbols->pop_scope();
}
;
+
+/* layout_qualifieropt is packed into this rule */
+uniform_block:
+ UNIFORM NEW_IDENTIFIER '{' member_list '}' ';'
+ {
+ void *ctx = state;
+ ast_type_qualifier no_qual;
+ memset(&no_qual, 0, sizeof(no_qual));
+ $$ = new(ctx) ast_uniform_block(no_qual, $2, $4);
+ }
+ | layout_qualifier UNIFORM NEW_IDENTIFIER '{' member_list '}' ';'
+ {
+ void *ctx = state;
+ $$ = new(ctx) ast_uniform_block($1, $3, $5);
+ }
+ ;
+
+member_list:
+ member_declaration
+ {
+ $$ = $1;
+ $1->link.self_link();
+ }
+ | member_declaration member_list
+ {
+ $$ = $1;
+ $2->link.insert_before(& $$->link);
+ }
+ ;
+
+/* Specifying "uniform" inside of a uniform block is redundant. */
+uniformopt:
+ /* nothing */
+ | UNIFORM
+ ;
+
+member_declaration:
+ layout_qualifier uniformopt type_specifier struct_declarator_list ';'
+ {
+ void *ctx = state;
+ ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+ type->set_location(yylloc);
+
+ type->qualifier = $1;
+ type->qualifier.flags.q.uniform = true;
+ type->specifier = $3;
+ $$ = new(ctx) ast_declarator_list(type);
+ $$->set_location(yylloc);
+
+ $$->declarations.push_degenerate_list_at_head(& $4->link);
+ }
+ | uniformopt type_specifier struct_declarator_list ';'
+ {
+ void *ctx = state;
+ ast_fully_specified_type *type = new(ctx) ast_fully_specified_type();
+ type->set_location(yylloc);
+
+ type->qualifier.flags.q.uniform = true;
+ type->specifier = $2;
+ $$ = new(ctx) ast_declarator_list(type);
+ $$->set_location(yylloc);
+
+ $$->declarations.push_degenerate_list_at_head(& $3->link);
+ }
+ ;