glsl: Add support for default precision statements
authorChad Versace <chad.versace@intel.com>
Mon, 17 Jan 2011 05:44:57 +0000 (21:44 -0800)
committerChad Versace <chad.versace@intel.com>
Mon, 17 Jan 2011 18:20:47 +0000 (10:20 -0800)
* Add new field ast_type_specifier::is_precision_statement.
* Add semantic checks in ast_type_specifier::hir().
* Alter parser rules accordingly.

src/glsl/ast.h
src/glsl/ast_to_hir.cpp
src/glsl/ast_type.cpp
src/glsl/glsl_parser.ypp

index 2b9b7861b0fb4b02f65c222e5dc2621bc1c280cf..0e2811ca665022e20988345e7c3cb040ee6e352f 100644 (file)
@@ -462,7 +462,8 @@ public:
    /** Construct a type specifier from a type name */
    ast_type_specifier(const char *name) 
       : type_specifier(ast_type_name), type_name(name), structure(NULL),
-       is_array(false), array_size(NULL), precision(ast_precision_none)
+       is_array(false), array_size(NULL), precision(ast_precision_none),
+       is_precision_statement(false)
    {
       /* empty */
    }
@@ -470,7 +471,8 @@ public:
    /** Construct a type specifier from a structure definition */
    ast_type_specifier(ast_struct_specifier *s)
       : type_specifier(ast_struct), type_name(s->name), structure(s),
-       is_array(false), array_size(NULL), precision(ast_precision_none)
+       is_array(false), array_size(NULL), precision(ast_precision_none),
+       is_precision_statement(false)
    {
       /* empty */
    }
@@ -492,6 +494,8 @@ public:
    ast_expression *array_size;
 
    unsigned precision:2;
+
+   bool is_precision_statement;
 };
 
 
index 764c549005f63e30e2d5f89bbe25c249b2453cfa..e3164d8c6171d3289ddd92aa926bf2b0e5e59331 100644 (file)
@@ -3239,6 +3239,58 @@ ir_rvalue *
 ast_type_specifier::hir(exec_list *instructions,
                          struct _mesa_glsl_parse_state *state)
 {
+   if (!this->is_precision_statement && this->structure == NULL)
+      return NULL;
+
+   YYLTYPE loc = this->get_location();
+
+   if (this->precision != ast_precision_none
+       && state->language_version != 100
+       && state->language_version < 130) {
+      _mesa_glsl_error(&loc, state,
+                       "precision qualifiers exist only in "
+                       "GLSL ES 1.00, and GLSL 1.30 and later");
+      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.
+    *
+    * From section 4.5.3 of the GLSL 1.30 spec:
+    *    "The precision statement
+    *       precision precision-qualifier type;
+    *    can be used to establish a default precision qualifier. The type
+    *    field can be either int or float [...].  Any other types or
+    *    qualifiers will result in an error.
+    */
+   if (this->is_precision_statement) {
+      assert(this->precision != ast_precision_none);
+      assert(this->structure == NULL); /* The check for structures was
+                                        * performed above. */
+      if (this->is_array) {
+         _mesa_glsl_error(&loc, state,
+                          "default precision statements do not apply to "
+                          "arrays");
+         return NULL;
+      }
+      if (this->type_specifier != ast_float
+          && this->type_specifier != ast_int) {
+         _mesa_glsl_error(&loc, state,
+                          "default precision statements apply only to types "
+                          "float and int");
+         return NULL;
+      }
+
+      /* FINISHME: Translate precision statements into IR. */
+      return NULL;
+   }
+
    if (this->structure != NULL)
       return this->structure->hir(instructions, state);
 
index f9c371514f5ce040331eaf620821b7377e8081e8..d14077473f0fc0c83b96e8eea12049fd236006a0 100644 (file)
@@ -49,7 +49,8 @@ ast_type_specifier::print(void) const
 
 ast_type_specifier::ast_type_specifier(int specifier)
       : type_specifier(ast_types(specifier)), type_name(NULL), structure(NULL),
-       is_array(false), array_size(NULL), precision(ast_precision_none)
+       is_array(false), array_size(NULL), precision(ast_precision_none),
+       is_precision_statement(false)
 {
    static const char *const names[] = {
       "void",
index 903d3f099032d57f9e19f514688136002fb38775..d0941ecef7dcea334509dfc31dd3bab11138df37 100644 (file)
@@ -276,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);
@@ -708,8 +708,9 @@ declaration:
                               "only be applied to `int' or `float'\n");
              YYERROR;
           }
-
-          $$ = NULL; /* FINISHME */
+          $3->precision = $2;
+          $3->is_precision_statement = true;
+          $$ = $3;
        }
        ;