glsl: Fix dependencies / linkage for glsl_compiler
[mesa.git] / src / glsl / glsl_parser.ypp
index 9d311093ba619ff2417316930caa17445ffd14d1..7336b18cdccd86d6673915658d18ee9a5ac109cc 100644 (file)
    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;
 %token VERSION EXTENSION LINE COLON EOL INTERFACE OUTPUT
 %token PRAGMA_DEBUG_ON PRAGMA_DEBUG_OFF
 %token PRAGMA_OPTIMIZE_ON PRAGMA_OPTIMIZE_OFF
+%token PRAGMA_INVARIANT_ALL
 %token LAYOUT_TOK
 
    /* Reserved words that are not actually used in the grammar.
 %token IIMAGE1D IIMAGE2D IIMAGE3D IIMAGECUBE IIMAGE1DARRAY IIMAGE2DARRAY
 %token UIMAGE1D UIMAGE2D UIMAGE3D UIMAGECUBE UIMAGE1DARRAY UIMAGE2DARRAY
 %token IMAGE1DSHADOW IMAGE2DSHADOW IMAGEBUFFER IIMAGEBUFFER UIMAGEBUFFER
+%token IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW
 %token ROW_MAJOR
 
 %type <identifier> variable_identifier
@@ -229,6 +228,11 @@ version_statement:
           case 130:
              /* FINISHME: Check against implementation support versions. */
              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);
              break;
           default:
              _mesa_glsl_error(& @2, state, "Shading language version"
@@ -243,6 +247,16 @@ pragma_statement:
        | PRAGMA_DEBUG_OFF EOL
        | PRAGMA_OPTIMIZE_ON EOL
        | PRAGMA_OPTIMIZE_OFF EOL
+       | PRAGMA_INVARIANT_ALL EOL
+       {
+          if (state->language_version < 120) {
+             _mesa_glsl_warning(& @1, state,
+                                "pragma `invariant(all)' not supported in %s",
+                                state->version_string);
+          } else {
+             state->all_invariant = true;
+          }
+       }
        ;
 
 extension_statement_list:
@@ -262,16 +276,16 @@ extension_statement:
 external_declaration_list:
        external_declaration
        {
-          /* FINISHME: The NULL test is only required because 'precision'
-           * FINISHME: statements are not yet supported.
+          /* FINISHME: The NULL test is required because pragmas are set to
+           * FINISHME: NULL. (See production rule for external_declaration.)
            */
           if ($1 != NULL)
              state->translation_unit.push_tail(& $1->link);
        }
        | external_declaration_list external_declaration
        {
-          /* FINISHME: The NULL test is only required because 'precision'
-           * FINISHME: statements are not yet supported.
+          /* FINISHME: The NULL test is required because pragmas are set to
+           * FINISHME: NULL. (See production rule for external_declaration.)
            */
           if ($2 != NULL)
              state->translation_unit.push_tail(& $2->link);
@@ -564,7 +578,7 @@ and_expression:
        | and_expression '&' equality_expression
        {
           void *ctx = state;
-          $$ = new(ctx) ast_expression_bin(ast_bit_or, $1, $3);
+          $$ = new(ctx) ast_expression_bin(ast_bit_and, $1, $3);
           $$->set_location(yylloc);
        }
        ;
@@ -688,14 +702,9 @@ declaration:
        }
        | PRECISION precision_qualifier type_specifier_no_prec ';'
        {
-          if (($3->type_specifier != ast_float)
-              && ($3->type_specifier != ast_int)) {
-             _mesa_glsl_error(& @3, state, "global precision qualifier can "
-                              "only be applied to `int' or `float'\n");
-             YYERROR;
-          }
-
-          $$ = NULL; /* FINISHME */
+          $3->precision = $2;
+          $3->is_precision_statement = true;
+          $$ = $3;
        }
        ;
 
@@ -760,25 +769,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 +796,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,7 +979,7 @@ fully_specified_type:
           void *ctx = state;
           $$ = new(ctx) ast_fully_specified_type();
           $$->set_location(yylloc);
-          $$->qualifier = $1.q;
+          $$->qualifier = $1;
           $$->specifier = $2;
        }
        ;
@@ -970,52 +995,139 @@ 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($$));
 
+          /* Layout qualifiers for ARB_fragment_coord_conventions. */
+          if (!got_one && 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) {
+             if (got_one && 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) {
+             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) {
+                _mesa_glsl_warning(& @1, state,
+                                   "GL_AMD_conservative_depth "
+                                   "layout qualifier `%s' is used\n", $1);
+             }
+          }
+
+          if (!got_one) {
+             _mesa_glsl_error(& @1, state, "unrecognized layout identifier "
+                              "`%s'\n", $1);
+             YYERROR;
+          }
+       }
+       | 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:
@@ -1023,44 +1135,87 @@ type_qualifier:
        | layout_qualifier
        | layout_qualifier storage_qualifier
        {
-          $$.i = $1.i | $2.i;
+          $$ = $1;
+          $$.flags.i |= $2.flags.i;
        }
        | interpolation_qualifier
        | interpolation_qualifier storage_qualifier
        {
-          $$.i = $1.i | $2.i;
+          $$ = $1;
+          $$.flags.i |= $2.flags.i;
        }
        | INVARIANT storage_qualifier
        {
           $$ = $2;
-          $$.q.invariant = 1;
+          $$.flags.q.invariant = 1;
        }
        | INVARIANT interpolation_qualifier storage_qualifier
        {
-          $$.i = $2.i | $3.i;
-          $$.q.invariant = 1;
+          $$ = $2;
+          $$.flags.i |= $3.flags.i;
+          $$.flags.q.invariant = 1;
        }
        | INVARIANT
        {
-          $$.i = 0;
-          $$.q.invariant = 1;
+          memset(& $$, 0, sizeof($$));
+          $$.flags.q.invariant = 1;
        }
        ;
 
 storage_qualifier:
-       CONST_TOK               { $$.i = 0; $$.q.constant = 1; }
-       | ATTRIBUTE             { $$.i = 0; $$.q.attribute = 1; }
-       | VARYING               { $$.i = 0; $$.q.varying = 1; }
-       | CENTROID VARYING      { $$.i = 0; $$.q.centroid = 1; $$.q.varying = 1; }
-       | 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:
        type_specifier_no_prec
+       {
+          $$ = $1;
+       }
        | precision_qualifier type_specifier_no_prec
        {
           $$ = $2;
@@ -1164,10 +1319,9 @@ precision_qualifier:
                     if (!state->es_shader && state->language_version < 130)
                        _mesa_glsl_error(& @1, state,
                                         "precision qualifier forbidden "
-                                        "in GLSL %d.%d (1.30 or later "
+                                        "in %s (1.30 or later "
                                         "required)\n",
-                                        state->language_version / 100,
-                                        state->language_version % 100);
+                                        state->version_string);
 
                     $$ = ast_precision_high;
                  }
@@ -1175,10 +1329,9 @@ precision_qualifier:
                     if (!state->es_shader && state->language_version < 130)
                        _mesa_glsl_error(& @1, state,
                                         "precision qualifier forbidden "
-                                        "in GLSL %d.%d (1.30 or later "
+                                        "in %s (1.30 or later "
                                         "required)\n",
-                                        state->language_version / 100,
-                                        state->language_version % 100);
+                                        state->version_string);
 
                     $$ = ast_precision_medium;
                  }
@@ -1186,10 +1339,9 @@ precision_qualifier:
                     if (!state->es_shader && state->language_version < 130)
                        _mesa_glsl_error(& @1, state,
                                         "precision qualifier forbidden "
-                                        "in GLSL %d.%d (1.30 or later "
+                                        "in %s (1.30 or later "
                                         "required)\n",
-                                        state->language_version / 100,
-                                        state->language_version % 100);
+                                        state->version_string);
 
                     $$ = ast_precision_low;
                  }