X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Fglsl_parser.yy;h=78f5bf6f4f2038e318e09f2b27a9c4713136b278;hb=b2265db8e77b531e380c47bb5bf31a3c0aa36e08;hp=1851f1e202e298ad1bf7a4a8e0d1a7d7d28a28b8;hpb=547212d963c70161915c46d64e8020617199fb8d;p=mesa.git diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 1851f1e202e..78f5bf6f4f2 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -29,9 +29,16 @@ #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_types.h" +#include "main/context.h" #define YYLEX_PARAM state->scanner +#undef yyerror + +static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg) +{ + _mesa_glsl_error(loc, st, "%s", msg); +} %} %pure-parser @@ -52,7 +59,7 @@ %union { int n; float real; - char *identifier; + const char *identifier; struct ast_type_qualifier type_qualifier; @@ -67,6 +74,12 @@ ast_declarator_list *declarator_list; ast_struct_specifier *struct_specifier; ast_declaration *declaration; + ast_switch_body *switch_body; + ast_case_label *case_label; + ast_case_label_list *case_label_list; + ast_case_statement *case_statement; + ast_case_statement_list *case_statement_list; + ast_interface_block *interface_block; struct { ast_node *cond; @@ -89,12 +102,20 @@ %token MAT4X2 MAT4X3 MAT4X4 %token SAMPLER1D SAMPLER2D SAMPLER3D SAMPLERCUBE SAMPLER1DSHADOW SAMPLER2DSHADOW %token SAMPLERCUBESHADOW SAMPLER1DARRAY SAMPLER2DARRAY SAMPLER1DARRAYSHADOW -%token SAMPLER2DARRAYSHADOW ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE -%token ISAMPLER1DARRAY ISAMPLER2DARRAY USAMPLER1D USAMPLER2D USAMPLER3D -%token USAMPLERCUBE USAMPLER1DARRAY USAMPLER2DARRAY +%token SAMPLER2DARRAYSHADOW SAMPLERCUBEARRAY SAMPLERCUBEARRAYSHADOW +%token ISAMPLER1D ISAMPLER2D ISAMPLER3D ISAMPLERCUBE +%token ISAMPLER1DARRAY ISAMPLER2DARRAY ISAMPLERCUBEARRAY +%token USAMPLER1D USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER1DARRAY +%token USAMPLER2DARRAY USAMPLERCUBEARRAY +%token SAMPLER2DRECT ISAMPLER2DRECT USAMPLER2DRECT SAMPLER2DRECTSHADOW +%token SAMPLERBUFFER ISAMPLERBUFFER USAMPLERBUFFER +%token SAMPLER2DMS ISAMPLER2DMS USAMPLER2DMS +%token SAMPLER2DMSARRAY ISAMPLER2DMSARRAY USAMPLER2DMSARRAY +%token SAMPLEREXTERNALOES %token STRUCT VOID_TOK WHILE %token IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER %type any_identifier +%type instance_name_opt %token FLOATCONSTANT %token INTCONSTANT UINTCONSTANT BOOLCONSTANT %token FIELD_SELECTION @@ -106,7 +127,7 @@ %token INVARIANT %token LOWP MEDIUMP HIGHP SUPERP PRECISION -%token VERSION EXTENSION LINE COLON EOL INTERFACE OUTPUT +%token VERSION_TOK EXTENSION LINE COLON EOL INTERFACE OUTPUT %token PRAGMA_DEBUG_ON PRAGMA_DEBUG_OFF %token PRAGMA_OPTIMIZE_ON PRAGMA_OPTIMIZE_OFF %token PRAGMA_INVARIANT_ALL @@ -118,12 +139,14 @@ %token INLINE_TOK NOINLINE VOLATILE PUBLIC_TOK STATIC EXTERN EXTERNAL %token LONG_TOK SHORT_TOK DOUBLE_TOK HALF FIXED_TOK UNSIGNED INPUT_TOK OUPTUT %token HVEC2 HVEC3 HVEC4 DVEC2 DVEC3 DVEC4 FVEC2 FVEC3 FVEC4 -%token SAMPLER2DRECT SAMPLER3DRECT SAMPLER2DRECTSHADOW +%token SAMPLER3DRECT %token SIZEOF CAST NAMESPACE USING +%token COHERENT RESTRICT READONLY WRITEONLY RESOURCE ATOMIC_UINT PATCH SAMPLE +%token SUBROUTINE %token ERROR_TOK -%token COMMON PARTITION ACTIVE SAMPLERBUFFER FILTER +%token COMMON PARTITION ACTIVE FILTER %token IMAGE1D IMAGE2D IMAGE3D IMAGECUBE IMAGE1DARRAY IMAGE2DARRAY %token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGECUBE IIMAGE1DARRAY IIMAGE2DARRAY %token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGECUBE UIMAGE1DARRAY UIMAGE2DARRAY @@ -141,10 +164,12 @@ %type interpolation_qualifier %type layout_qualifier %type layout_qualifier_id_list layout_qualifier_id +%type interface_block_layout_qualifier +%type interface_qualifier %type type_specifier %type type_specifier_no_prec %type type_specifier_nonarray -%type basic_type_specifier_nonarray +%type basic_type_specifier_nonarray %type fully_specified_type %type function_prototype %type function_header @@ -196,21 +221,33 @@ %type init_declarator_list %type single_declaration %type initializer +%type initializer_list %type declaration %type declaration_statement %type jump_statement +%type interface_block +%type basic_interface_block %type struct_specifier -%type struct_declaration_list +%type struct_declaration_list %type struct_declaration %type struct_declarator %type struct_declarator_list +%type member_list +%type member_declaration %type selection_statement %type selection_rest_statement +%type switch_statement +%type switch_body +%type case_label_list +%type case_label +%type case_statement +%type case_statement_list %type iteration_statement %type condition %type conditionopt %type for_init_statement %type for_rest_statement +%type integer_constant %% translation_unit: @@ -228,43 +265,20 @@ translation_unit: version_statement: /* blank - no #version specified: defaults are already set */ - | VERSION INTCONSTANT EOL - { - bool supported = false; - - switch ($2) { - case 100: - state->es_shader = true; - supported = state->Const.GLSL_100ES; - break; - case 110: - supported = state->Const.GLSL_110; - break; - case 120: - supported = state->Const.GLSL_120; - break; - case 130: - supported = state->Const.GLSL_130; - break; - default: - supported = false; - break; - } - - state->language_version = $2; - state->version_string = - ralloc_asprintf(state, "GLSL%s %d.%02d", - state->es_shader ? " ES" : "", - state->language_version / 100, - state->language_version % 100); - - if (!supported) { - _mesa_glsl_error(& @2, state, "%s is not supported. " - "Supported versions are: %s\n", - state->version_string, - state->supported_version_string); + | VERSION_TOK INTCONSTANT EOL + { + state->process_version_directive(&@2, $2, NULL); + if (state->error) { + YYERROR; } } + | VERSION_TOK INTCONSTANT any_identifier EOL + { + state->process_version_directive(&@2, $2, $3); + if (state->error) { + YYERROR; + } + } ; pragma_statement: @@ -274,10 +288,11 @@ pragma_statement: | PRAGMA_OPTIMIZE_OFF EOL | PRAGMA_INVARIANT_ALL EOL { - if (state->language_version < 120) { + if (!state->is_version(120, 100)) { _mesa_glsl_warning(& @1, state, - "pragma `invariant(all)' not supported in %s", - state->version_string); + "pragma `invariant(all)' not supported in %s " + "(GLSL ES 1.00 or GLSL 1.20 required).", + state->get_version_string()); } else { state->all_invariant = true; } @@ -777,6 +792,10 @@ declaration: $3->is_precision_statement = true; $$ = $3; } + | interface_block + { + $$ = $1; + } ; function_prototype: @@ -943,6 +962,11 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($7->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, NULL); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | init_declarator_list ',' any_identifier '[' constant_expression ']' '=' initializer { @@ -953,6 +977,11 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($8->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$8; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->type->specifier, true, $5); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | init_declarator_list ',' any_identifier '=' initializer { @@ -963,6 +992,10 @@ init_declarator_list: $$ = $1; $$->declarations.push_tail(&decl->link); state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + if ($5->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$5; + _mesa_ast_set_aggregate_type($1->type->specifier, ai, state); + } } ; @@ -1010,6 +1043,11 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($6->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$6; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, NULL); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | fully_specified_type any_identifier '[' constant_expression ']' '=' initializer { @@ -1019,6 +1057,11 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($7->oper == ast_aggregate) { + ast_aggregate_initializer *ai = (ast_aggregate_initializer *)$7; + ast_type_specifier *type = new(ctx) ast_type_specifier($1->specifier, true, $4); + _mesa_ast_set_aggregate_type(type, ai, state); + } } | fully_specified_type any_identifier '=' initializer { @@ -1028,6 +1071,9 @@ single_declaration: $$ = new(ctx) ast_declarator_list($1); $$->set_location(yylloc); $$->declarations.push_tail(&decl->link); + if ($4->oper == ast_aggregate) { + _mesa_ast_set_aggregate_type($1->specifier, $4, state); + } } | INVARIANT variable_identifier // Vertex only. { @@ -1071,88 +1117,101 @@ layout_qualifier_id_list: layout_qualifier_id | layout_qualifier_id_list ',' layout_qualifier_id { - if (($1.flags.i & $3.flags.i) != 0) { - _mesa_glsl_error(& @3, state, - "duplicate layout qualifiers used\n"); + $$ = $1; + if (!$$.merge_qualifier(& @3, state, $3)) { 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; } ; +integer_constant: + INTCONSTANT { $$ = $1; } + | UINTCONSTANT { $$ = $1; } + ; + 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); } } - /* Layout qualifiers for AMD_conservative_depth. */ - if (!got_one && state->AMD_conservative_depth_enable) { + /* Layout qualifiers for AMD/ARB_conservative_depth. */ + 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 ($$.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 interface_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; + /* "row_major" is a reserved word in GLSL 1.30+. Its token is parsed + * below in the interface_block_layout_qualifier rule. + * + * It is not a reserved word in GLSL ES 3.00, so it's handled here as + * an identifier. + */ + } else if (strcmp($1, "row_major") == 0) { + $$.flags.q.row_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; } } - | any_identifier '=' INTCONSTANT + | any_identifier '=' integer_constant { - 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) { @@ -1163,12 +1222,24 @@ layout_qualifier_id: YYERROR; } } + + if (strcmp("index", $1) == 0) { + $$.flags.q.explicit_index = 1; + + if ($3 >= 0) { + $$.index = $3; + } else { + _mesa_glsl_error(& @3, state, + "invalid index %d specified\n", $3); + YYERROR; + } + } } /* 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; @@ -1178,6 +1249,38 @@ layout_qualifier_id: "identifier `%s' used\n", $1); } } + | interface_block_layout_qualifier + { + $$ = $1; + /* Layout qualifiers for ARB_uniform_buffer_object. */ + if ($$.flags.q.uniform && !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 ($$.flags.q.uniform && 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. + */ +interface_block_layout_qualifier: + ROW_MAJOR + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.row_major = 1; + } + | PACKED_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.packed = 1; + } ; interpolation_qualifier: @@ -1337,87 +1440,88 @@ type_specifier_nonarray: ; basic_type_specifier_nonarray: - VOID_TOK { $$ = ast_void; } - | FLOAT_TOK { $$ = ast_float; } - | INT_TOK { $$ = ast_int; } - | UINT_TOK { $$ = ast_uint; } - | BOOL_TOK { $$ = ast_bool; } - | VEC2 { $$ = ast_vec2; } - | VEC3 { $$ = ast_vec3; } - | VEC4 { $$ = ast_vec4; } - | BVEC2 { $$ = ast_bvec2; } - | BVEC3 { $$ = ast_bvec3; } - | BVEC4 { $$ = ast_bvec4; } - | IVEC2 { $$ = ast_ivec2; } - | IVEC3 { $$ = ast_ivec3; } - | IVEC4 { $$ = ast_ivec4; } - | UVEC2 { $$ = ast_uvec2; } - | UVEC3 { $$ = ast_uvec3; } - | UVEC4 { $$ = ast_uvec4; } - | MAT2X2 { $$ = ast_mat2; } - | MAT2X3 { $$ = ast_mat2x3; } - | MAT2X4 { $$ = ast_mat2x4; } - | MAT3X2 { $$ = ast_mat3x2; } - | MAT3X3 { $$ = ast_mat3; } - | MAT3X4 { $$ = ast_mat3x4; } - | MAT4X2 { $$ = ast_mat4x2; } - | MAT4X3 { $$ = ast_mat4x3; } - | MAT4X4 { $$ = ast_mat4; } - | SAMPLER1D { $$ = ast_sampler1d; } - | SAMPLER2D { $$ = ast_sampler2d; } - | SAMPLER2DRECT { $$ = ast_sampler2drect; } - | SAMPLER3D { $$ = ast_sampler3d; } - | SAMPLERCUBE { $$ = ast_samplercube; } - | SAMPLER1DSHADOW { $$ = ast_sampler1dshadow; } - | SAMPLER2DSHADOW { $$ = ast_sampler2dshadow; } - | SAMPLER2DRECTSHADOW { $$ = ast_sampler2drectshadow; } - | SAMPLERCUBESHADOW { $$ = ast_samplercubeshadow; } - | SAMPLER1DARRAY { $$ = ast_sampler1darray; } - | SAMPLER2DARRAY { $$ = ast_sampler2darray; } - | SAMPLER1DARRAYSHADOW { $$ = ast_sampler1darrayshadow; } - | SAMPLER2DARRAYSHADOW { $$ = ast_sampler2darrayshadow; } - | ISAMPLER1D { $$ = ast_isampler1d; } - | ISAMPLER2D { $$ = ast_isampler2d; } - | ISAMPLER3D { $$ = ast_isampler3d; } - | ISAMPLERCUBE { $$ = ast_isamplercube; } - | ISAMPLER1DARRAY { $$ = ast_isampler1darray; } - | ISAMPLER2DARRAY { $$ = ast_isampler2darray; } - | USAMPLER1D { $$ = ast_usampler1d; } - | USAMPLER2D { $$ = ast_usampler2d; } - | USAMPLER3D { $$ = ast_usampler3d; } - | USAMPLERCUBE { $$ = ast_usamplercube; } - | USAMPLER1DARRAY { $$ = ast_usampler1darray; } - | USAMPLER2DARRAY { $$ = ast_usampler2darray; } + VOID_TOK { $$ = "void"; } + | FLOAT_TOK { $$ = "float"; } + | INT_TOK { $$ = "int"; } + | UINT_TOK { $$ = "uint"; } + | BOOL_TOK { $$ = "bool"; } + | VEC2 { $$ = "vec2"; } + | VEC3 { $$ = "vec3"; } + | VEC4 { $$ = "vec4"; } + | BVEC2 { $$ = "bvec2"; } + | BVEC3 { $$ = "bvec3"; } + | BVEC4 { $$ = "bvec4"; } + | IVEC2 { $$ = "ivec2"; } + | IVEC3 { $$ = "ivec3"; } + | IVEC4 { $$ = "ivec4"; } + | UVEC2 { $$ = "uvec2"; } + | UVEC3 { $$ = "uvec3"; } + | UVEC4 { $$ = "uvec4"; } + | MAT2X2 { $$ = "mat2"; } + | MAT2X3 { $$ = "mat2x3"; } + | MAT2X4 { $$ = "mat2x4"; } + | MAT3X2 { $$ = "mat3x2"; } + | MAT3X3 { $$ = "mat3"; } + | MAT3X4 { $$ = "mat3x4"; } + | MAT4X2 { $$ = "mat4x2"; } + | MAT4X3 { $$ = "mat4x3"; } + | MAT4X4 { $$ = "mat4"; } + | SAMPLER1D { $$ = "sampler1D"; } + | SAMPLER2D { $$ = "sampler2D"; } + | SAMPLER2DRECT { $$ = "sampler2DRect"; } + | SAMPLER3D { $$ = "sampler3D"; } + | SAMPLERCUBE { $$ = "samplerCube"; } + | SAMPLEREXTERNALOES { $$ = "samplerExternalOES"; } + | SAMPLER1DSHADOW { $$ = "sampler1DShadow"; } + | SAMPLER2DSHADOW { $$ = "sampler2DShadow"; } + | SAMPLER2DRECTSHADOW { $$ = "sampler2DRectShadow"; } + | SAMPLERCUBESHADOW { $$ = "samplerCubeShadow"; } + | SAMPLER1DARRAY { $$ = "sampler1DArray"; } + | SAMPLER2DARRAY { $$ = "sampler2DArray"; } + | SAMPLER1DARRAYSHADOW { $$ = "sampler1DArrayShadow"; } + | SAMPLER2DARRAYSHADOW { $$ = "sampler2DArrayShadow"; } + | SAMPLERBUFFER { $$ = "samplerBuffer"; } + | SAMPLERCUBEARRAY { $$ = "samplerCubeArray"; } + | SAMPLERCUBEARRAYSHADOW { $$ = "samplerCubeArrayShadow"; } + | ISAMPLER1D { $$ = "isampler1D"; } + | ISAMPLER2D { $$ = "isampler2D"; } + | ISAMPLER2DRECT { $$ = "isampler2DRect"; } + | ISAMPLER3D { $$ = "isampler3D"; } + | ISAMPLERCUBE { $$ = "isamplerCube"; } + | ISAMPLER1DARRAY { $$ = "isampler1DArray"; } + | ISAMPLER2DARRAY { $$ = "isampler2DArray"; } + | ISAMPLERBUFFER { $$ = "isamplerBuffer"; } + | ISAMPLERCUBEARRAY { $$ = "isamplerCubeArray"; } + | USAMPLER1D { $$ = "usampler1D"; } + | USAMPLER2D { $$ = "usampler2D"; } + | USAMPLER2DRECT { $$ = "usampler2DRect"; } + | USAMPLER3D { $$ = "usampler3D"; } + | USAMPLERCUBE { $$ = "usamplerCube"; } + | USAMPLER1DARRAY { $$ = "usampler1DArray"; } + | USAMPLER2DARRAY { $$ = "usampler2DArray"; } + | USAMPLERBUFFER { $$ = "usamplerBuffer"; } + | USAMPLERCUBEARRAY { $$ = "usamplerCubeArray"; } + | SAMPLER2DMS { $$ = "sampler2DMS"; } + | ISAMPLER2DMS { $$ = "isampler2DMS"; } + | USAMPLER2DMS { $$ = "usampler2DMS"; } + | SAMPLER2DMSARRAY { $$ = "sampler2DMSArray"; } + | ISAMPLER2DMSARRAY { $$ = "isampler2DMSArray"; } + | USAMPLER2DMSARRAY { $$ = "usampler2DMSArray"; } ; precision_qualifier: HIGHP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_high; } | MEDIUMP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_medium; } | LOWP { - if (!state->es_shader && state->language_version < 130) - _mesa_glsl_error(& @1, state, - "precision qualifier forbidden " - "in %s (1.30 or later " - "required)\n", - state->version_string); + state->check_precision_qualifiers_allowed(&@1); $$ = ast_precision_low; } @@ -1430,6 +1534,7 @@ struct_specifier: $$ = new(ctx) ast_struct_specifier($2, $4); $$->set_location(yylloc); state->symbols->add_type($2, glsl_type::void_type); + state->symbols->add_type_ast($2, new(ctx) ast_type_specifier($$)); } | STRUCT '{' struct_declaration_list '}' { @@ -1442,12 +1547,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); } ; @@ -1486,7 +1591,6 @@ struct_declarator: 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)); } | any_identifier '[' constant_expression ']' { @@ -1498,6 +1602,28 @@ struct_declarator: initializer: assignment_expression + | '{' initializer_list '}' + { + $$ = $2; + } + | '{' initializer_list ',' '}' + { + $$ = $2; + } + ; + +initializer_list: + initializer + { + void *ctx = state; + $$ = new(ctx) ast_aggregate_initializer(); + $$->set_location(yylloc); + $$->expressions.push_tail(& $1->link); + } + | initializer_list ',' initializer + { + $1->expressions.push_tail(& $3->link); + } ; declaration_statement: @@ -1515,8 +1641,7 @@ simple_statement: declaration_statement | expression_statement | selection_statement - | switch_statement { $$ = NULL; } - | case_label { $$ = NULL; } + | switch_statement | iteration_statement | jump_statement ; @@ -1638,13 +1763,90 @@ condition: } ; +/* + * siwtch_statement grammar is based on the syntax described in the body + * of the GLSL spec, not in it's appendix!!! + */ switch_statement: - SWITCH '(' expression ')' compound_statement + SWITCH '(' expression ')' switch_body + { + $$ = new(state) ast_switch_statement($3, $5); + $$->set_location(yylloc); + } + ; + +switch_body: + '{' '}' + { + $$ = new(state) ast_switch_body(NULL); + $$->set_location(yylloc); + } + | '{' case_statement_list '}' + { + $$ = new(state) ast_switch_body($2); + $$->set_location(yylloc); + } ; case_label: CASE expression ':' + { + $$ = new(state) ast_case_label($2); + $$->set_location(yylloc); + } | DEFAULT ':' + { + $$ = new(state) ast_case_label(NULL); + $$->set_location(yylloc); + } + ; + +case_label_list: + case_label + { + ast_case_label_list *labels = new(state) ast_case_label_list(); + + labels->labels.push_tail(& $1->link); + $$ = labels; + $$->set_location(yylloc); + } + | case_label_list case_label + { + $$ = $1; + $$->labels.push_tail(& $2->link); + } + ; + +case_statement: + case_label_list statement + { + ast_case_statement *stmts = new(state) ast_case_statement($1); + stmts->set_location(yylloc); + + stmts->stmts.push_tail(& $2->link); + $$ = stmts; + } + | case_statement statement + { + $$ = $1; + $$->stmts.push_tail(& $2->link); + } + ; + +case_statement_list: + case_statement + { + ast_case_statement_list *cases= new(state) ast_case_statement_list(); + cases->set_location(yylloc); + + cases->cases.push_tail(& $1->link); + $$ = cases; + } + | case_statement_list case_statement + { + $$ = $1; + $$->cases.push_tail(& $2->link); + } ; iteration_statement: @@ -1735,6 +1937,7 @@ external_declaration: function_definition { $$ = $1; } | declaration { $$ = $1; } | pragma_statement { $$ = NULL; } + | layout_defaults { $$ = NULL; } ; function_definition: @@ -1749,3 +1952,211 @@ function_definition: state->symbols->pop_scope(); } ; + +/* layout_qualifieropt is packed into this rule */ +interface_block: + basic_interface_block + { + $$ = $1; + } + | layout_qualifier basic_interface_block + { + ast_interface_block *block = $2; + if (!block->layout.merge_qualifier(& @1, state, $1)) { + YYERROR; + } + $$ = block; + } + ; + +basic_interface_block: + interface_qualifier NEW_IDENTIFIER '{' member_list '}' instance_name_opt ';' + { + ast_interface_block *const block = $6; + + block->block_name = $2; + block->declarations.push_degenerate_list_at_head(& $4->link); + + if ($1.flags.q.uniform) { + if (!state->ARB_uniform_buffer_object_enable) { + _mesa_glsl_error(& @1, state, + "#version 140 / GL_ARB_uniform_buffer_object " + "required for defining uniform blocks\n"); + } else if (state->ARB_uniform_buffer_object_warn) { + _mesa_glsl_warning(& @1, state, + "#version 140 / GL_ARB_uniform_buffer_object " + "required for defining uniform blocks\n"); + } + } else { + if (state->es_shader || state->language_version < 150) { + _mesa_glsl_error(& @1, state, + "#version 150 required for using " + "interface blocks.\n"); + } + } + + /* From the GLSL 1.50.11 spec, section 4.3.7 ("Interface Blocks"): + * "It is illegal to have an input block in a vertex shader + * or an output block in a fragment shader" + */ + if ((state->target == vertex_shader) && $1.flags.q.in) { + _mesa_glsl_error(& @1, state, + "`in' interface block is not allowed for " + "a vertex shader\n"); + } else if ((state->target == fragment_shader) && $1.flags.q.out) { + _mesa_glsl_error(& @1, state, + "`out' interface block is not allowed for " + "a fragment shader\n"); + } + + /* Since block arrays require names, and both features are added in + * the same language versions, we don't have to explicitly + * version-check both things. + */ + if (block->instance_name != NULL) { + state->check_version(150, 300, & @1, "interface blocks with " + "an instance name are not allowed"); + } + + unsigned interface_type_mask; + struct ast_type_qualifier temp_type_qualifier; + + /* Get a bitmask containing only the in/out/uniform flags, allowing us + * to ignore other irrelevant flags like interpolation qualifiers. + */ + temp_type_qualifier.flags.i = 0; + temp_type_qualifier.flags.q.uniform = true; + temp_type_qualifier.flags.q.in = true; + temp_type_qualifier.flags.q.out = true; + interface_type_mask = temp_type_qualifier.flags.i; + + /* Get the block's interface qualifier. The interface_qualifier + * production rule guarantees that only one bit will be set (and + * it will be in/out/uniform). + */ + unsigned block_interface_qualifier = $1.flags.i; + + block->layout.flags.i |= block_interface_qualifier; + + foreach_list_typed (ast_declarator_list, member, link, &block->declarations) { + ast_type_qualifier& qualifier = member->type->qualifier; + if ((qualifier.flags.i & interface_type_mask) == 0) { + /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks): + * "If no optional qualifier is used in a member declaration, the + * qualifier of the variable is just in, out, or uniform as declared + * by interface-qualifier." + */ + qualifier.flags.i |= block_interface_qualifier; + } else if ((qualifier.flags.i & interface_type_mask) != + block_interface_qualifier) { + /* GLSLangSpec.1.50.11, 4.3.7 (Interface Blocks): + * "If optional qualifiers are used, they can include interpolation + * and storage qualifiers and they must declare an input, output, + * or uniform variable consistent with the interface qualifier of + * the block." + */ + _mesa_glsl_error(& @1, state, + "uniform/in/out qualifier on " + "interface block member does not match " + "the interface block\n"); + } + } + + $$ = block; + } + ; + +interface_qualifier: + IN_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.in = 1; + } + | OUT_TOK + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.out = 1; + } + | UNIFORM + { + memset(& $$, 0, sizeof($$)); + $$.flags.q.uniform = 1; + } + ; + +instance_name_opt: + /* empty */ + { + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + NULL, + NULL); + } + | NEW_IDENTIFIER + { + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + $1, + NULL); + } + | NEW_IDENTIFIER '[' constant_expression ']' + { + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + $1, + $3); + } + | NEW_IDENTIFIER '[' ']' + { + _mesa_glsl_error(& @1, state, + "instance block arrays must be explicitly sized\n"); + + $$ = new(state) ast_interface_block(*state->default_uniform_qualifier, + $1, + NULL); + } + ; + +member_list: + member_declaration + { + $$ = $1; + $1->link.self_link(); + } + | member_declaration member_list + { + $$ = $1; + $2->link.insert_before(& $$->link); + } + ; + +member_declaration: + fully_specified_type struct_declarator_list ';' + { + void *ctx = state; + ast_fully_specified_type *type = $1; + type->set_location(yylloc); + + if (type->qualifier.flags.q.attribute) { + _mesa_glsl_error(& @1, state, + "keyword 'attribute' cannot be used with " + "interface block member\n"); + } else if (type->qualifier.flags.q.varying) { + _mesa_glsl_error(& @1, state, + "keyword 'varying' cannot be used with " + "interface block member\n"); + } + + $$ = new(ctx) ast_declarator_list(type); + $$->set_location(yylloc); + $$->ubo_qualifiers_valid = true; + + $$->declarations.push_degenerate_list_at_head(& $2->link); + } + ; + +layout_defaults: + layout_qualifier UNIFORM ';' + { + if (!state->default_uniform_qualifier->merge_qualifier(& @1, state, + $1)) { + YYERROR; + } + }