glsl: Move precision handling to be part of qualifier handling.
authorKenneth Graunke <kenneth@whitecape.org>
Mon, 15 Jul 2013 22:58:29 +0000 (15:58 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Thu, 18 Jul 2013 23:57:23 +0000 (16:57 -0700)
This is necessary for the parser to be able to accept precision
qualifiers not immediately adjacent to the type, such as "const highp
inout float foo".

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/glsl/ast.h
src/glsl/ast_to_hir.cpp
src/glsl/glsl_parser.yy

index 1208704ff6df9e9b0d87e731fafade13f32c3927..6aede009c8cbe92ee8e446fcddd1002f8f40520a 100644 (file)
@@ -437,6 +437,9 @@ struct ast_type_qualifier {
       unsigned i;
    } flags;
 
+   /** Precision of the type (highp/medium/lowp). */
+   unsigned precision:2;
+
    /**
     * Location specified via GL_ARB_explicit_attrib_location layout
     *
@@ -533,7 +536,7 @@ public:
    ast_type_specifier(const ast_type_specifier *that, bool is_array,
                       ast_expression *array_size)
       : ast_node(), type_name(that->type_name), structure(that->structure),
-        is_array(is_array), array_size(array_size), precision(that->precision),
+        is_array(is_array), array_size(array_size),
         default_precision(that->default_precision)
    {
       /* empty */
@@ -542,7 +545,7 @@ public:
    /** Construct a type specifier from a type name */
    ast_type_specifier(const char *name) 
       : type_name(name), structure(NULL),
-       is_array(false), array_size(NULL), precision(ast_precision_none),
+       is_array(false), array_size(NULL),
        default_precision(ast_precision_none)
    {
       /* empty */
@@ -551,7 +554,7 @@ public:
    /** Construct a type specifier from a structure definition */
    ast_type_specifier(ast_struct_specifier *s)
       : type_name(s->name), structure(s),
-       is_array(false), array_size(NULL), precision(ast_precision_none),
+       is_array(false), array_size(NULL),
        default_precision(ast_precision_none)
    {
       /* empty */
@@ -571,8 +574,6 @@ public:
    bool is_array;
    ast_expression *array_size;
 
-   unsigned precision:2;
-
    /** For precision statements, this is the given precision; otherwise none. */
    unsigned default_precision:2;
 };
index c1a2af30aea291992109cc101a1f323ed3e2cf57..3ed6f0175031c69b492212929c2e50f89a91c857 100644 (file)
@@ -2544,6 +2544,12 @@ ast_declarator_list::hir(exec_list *instructions,
                             type_name);
         }
       }
+
+      if (this->type->qualifier.precision != ast_precision_none &&
+          this->type->specifier->structure != NULL) {
+         _mesa_glsl_error(&loc, state, "Precision qualifiers can't be applied "
+                          "to structures.\n");
+      }
    }
 
    foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
@@ -2846,7 +2852,7 @@ ast_declarator_list::hir(exec_list *instructions,
 
       /* Precision qualifiers exists only in GLSL versions 1.00 and >= 1.30.
        */
-      if (this->type->specifier->precision != ast_precision_none) {
+      if (this->type->qualifier.precision != ast_precision_none) {
          state->check_precision_qualifiers_allowed(&loc);
       }
 
@@ -2864,9 +2870,10 @@ ast_declarator_list::hir(exec_list *instructions,
        * From page 87 of the GLSL ES spec:
        *    "RESOLUTION: Allow sampler types to take a precision qualifier."
        */
-      if (this->type->specifier->precision != ast_precision_none
+      if (this->type->qualifier.precision != ast_precision_none
           && !var->type->is_float()
           && !var->type->is_integer()
+          && !var->type->is_record()
           && !(var->type->is_sampler() && state->es_shader)
           && !(var->type->is_array()
                && (var->type->fields.array->is_float()
@@ -3963,17 +3970,6 @@ ast_type_specifier::hir(exec_list *instructions,
 
    YYLTYPE loc = this->get_location();
 
-   if (this->precision != ast_precision_none
-       && !state->check_precision_qualifiers_allowed(&loc)) {
-      return NULL;
-   }
-   if (this->precision != ast_precision_none
-       && this->structure != NULL) {
-      _mesa_glsl_error(&loc, state,
-                       "precision qualifiers do not apply to structures");
-      return NULL;
-   }
-
    /* If this is a precision statement, check that the type to which it is
     * applied is either float or int.
     *
@@ -3985,9 +3981,15 @@ ast_type_specifier::hir(exec_list *instructions,
     *    qualifiers will result in an error.
     */
    if (this->default_precision != ast_precision_none) {
-      assert(this->precision != ast_precision_none);
-      assert(this->structure == NULL); /* The check for structures was
-                                        * performed above. */
+      if (!state->check_precision_qualifiers_allowed(&loc))
+         return NULL;
+
+      if (this->structure != NULL) {
+         _mesa_glsl_error(&loc, state,
+                          "precision qualifiers do not apply to structures");
+         return NULL;
+      }
+
       if (this->is_array) {
          _mesa_glsl_error(&loc, state,
                           "default precision statements do not apply to "
index 1a13f4855037a476b88c63d2b3ea91067b2349d8..08806a32bcf33eb7482cab3c0e8a0e6d15bea66f 100644 (file)
@@ -169,7 +169,6 @@ static void yyerror(YYLTYPE *loc, _mesa_glsl_parse_state *st, const char *msg)
 %type <type_qualifier> interface_block_layout_qualifier
 %type <type_qualifier> interface_qualifier
 %type <type_specifier> type_specifier
-%type <type_specifier> type_specifier_no_prec
 %type <type_specifier> type_specifier_nonarray
 %type <identifier> basic_type_specifier_nonarray
 %type <fully_specified_type> fully_specified_type
@@ -790,9 +789,8 @@ declaration:
    {
       $$ = $1;
    }
-   | PRECISION precision_qualifier type_specifier_no_prec ';'
+   | PRECISION precision_qualifier type_specifier ';'
    {
-      $3->precision = $2;
       $3->default_precision = $2;
       $$ = $3;
    }
@@ -905,6 +903,17 @@ parameter_qualifier:
       $$ = $1;
       $$.merge_qualifier(&@1, state, $2);
    }
+   | precision_qualifier parameter_qualifier
+   {
+      if ($2.precision != ast_precision_none)
+         _mesa_glsl_error(&@1, state, "Duplicate precision qualifier.\n");
+
+      if ($2.flags.i != 0)
+         _mesa_glsl_error(&@1, state, "Precision qualifiers must come last.\n");
+
+      $$ = $2;
+      $$.precision = $1;
+   }
 
 parameter_direction_qualifier:
    IN_TOK
@@ -1319,6 +1328,11 @@ type_qualifier:
    | storage_qualifier
    | interpolation_qualifier
    | layout_qualifier
+   | precision_qualifier
+   {
+      memset(&$$, 0, sizeof($$));
+      $$.precision = $1;
+   }
 
    /* Multiple qualifiers:
     * In GLSL 4.20, these can be specified in any order.  In earlier versions,
@@ -1414,6 +1428,17 @@ type_qualifier:
       $$ = $1;
       $$.merge_qualifier(&@1, state, $2);
    }
+   | precision_qualifier type_qualifier
+   {
+      if ($2.precision != ast_precision_none)
+         _mesa_glsl_error(&@1, state, "Duplicate precision qualifier.\n");
+
+      if ($2.flags.i != 0)
+         _mesa_glsl_error(&@1, state, "Precision qualifiers must come last.\n");
+
+      $$ = $2;
+      $$.precision = $1;
+   }
    ;
 
 storage_qualifier:
@@ -1466,18 +1491,6 @@ storage_qualifier:
    ;
 
 type_specifier:
-   type_specifier_no_prec
-   {
-      $$ = $1;
-   }
-   | precision_qualifier type_specifier_no_prec
-   {
-      $$ = $2;
-      $$->precision = $1;
-   }
-   ;
-
-type_specifier_no_prec:
    type_specifier_nonarray
    | type_specifier_nonarray '[' ']'
    {