glsl: Add support for `precise` redeclarations
authorChris Forbes <chrisf@ijw.co.nz>
Sun, 27 Apr 2014 04:03:54 +0000 (16:03 +1200)
committerChris Forbes <chrisf@ijw.co.nz>
Wed, 4 Jun 2014 06:56:05 +0000 (18:56 +1200)
This works like glsl-1.20+'s invariant redeclarations, but with fewer
restrictions, since `precise` is allowed on pretty much anything.

Signed-off-by: Chris Forbes <chrisf@ijw.co.nz>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
src/glsl/ast.h
src/glsl/ast_to_hir.cpp
src/glsl/glsl_parser.yy
src/glsl/glsl_parser_extras.cpp

index b0430de071ee7305c4b1735c105b2c6ad44ff6d6..56e7bd86f919d5c31c8f1e87e39f1d4fd70c2cc2 100644 (file)
@@ -746,13 +746,11 @@ public:
    exec_list declarations;
 
    /**
-    * Special flag for vertex shader "invariant" declarations.
-    *
-    * Vertex shaders can contain "invariant" variable redeclarations that do
-    * not include a type.  For example, "invariant gl_Position;".  This flag
-    * is used to note these cases when no type is specified.
+    * Flags for redeclarations. In these cases, no type is specified, to
+    * `type` is allowed to be NULL. In all other cases, this would be an error.
     */
-   int invariant;
+   int invariant;     /** < `invariant` redeclaration */
+   int precise;       /** < `precise` redeclaration */
 };
 
 
index 0b28b4814c42a7ac73f9f7cb3af918e13edbc6d4..a57ce5058e1775d9138ab2556515a906c47ccb8c 100644 (file)
@@ -3174,6 +3174,33 @@ ast_declarator_list::hir(exec_list *instructions,
       return NULL;
    }
 
+   if (this->precise) {
+      assert(this->type == NULL);
+
+      foreach_list_typed (ast_declaration, decl, link, &this->declarations) {
+         assert(decl->array_specifier == NULL);
+         assert(decl->initializer == NULL);
+
+         ir_variable *const earlier =
+            state->symbols->get_variable(decl->identifier);
+         if (earlier == NULL) {
+            _mesa_glsl_error(& loc, state,
+                             "undeclared variable `%s' cannot be marked "
+                             "precise", decl->identifier);
+         } else if (earlier->data.used) {
+            _mesa_glsl_error(& loc, state,
+                             "variable `%s' may not be redeclared "
+                             "`precise' after being used",
+                             earlier->name);
+         } else {
+            earlier->data.precise = true;
+         }
+      }
+
+      /* Precise redeclarations do not have r-values either. */
+      return NULL;
+   }
+
    assert(this->type != NULL);
    assert(!this->invariant);
    assert(!this->precise);
index 83cbb902b5daf08ebc1c3c31276eef61eedd7d5c..ba6bfa1e1fa0ecd6cd423d9a207130cc47fddeec 100644 (file)
@@ -1083,6 +1083,18 @@ single_declaration:
 
       $$->declarations.push_tail(&decl->link);
    }
+   | PRECISE variable_identifier
+   {
+      void *ctx = state;
+      ast_declaration *decl = new(ctx) ast_declaration($2, NULL, NULL);
+      decl->set_location(@2);
+
+      $$ = new(ctx) ast_declarator_list(NULL);
+      $$->set_location_range(@1, @2);
+      $$->precise = true;
+
+      $$->declarations.push_tail(&decl->link);
+   }
    ;
 
 fully_specified_type:
index d3339e7795d36f503d3d83a18a310e07fa8f4626..f3c5bd04938f3b17c717801a943fc564685bfd08 100644 (file)
@@ -1098,8 +1098,10 @@ ast_declarator_list::print(void) const
 
    if (type)
       type->print();
-   else
+   else if (invariant)
       printf("invariant ");
+   else
+      printf("precise ");
 
    foreach_list_const (ptr, & this->declarations) {
       if (ptr != this->declarations.get_head())
@@ -1117,6 +1119,7 @@ ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
 {
    this->type = type;
    this->invariant = false;
+   this->precise = false;
 }
 
 void