diff options
-rw-r--r-- | src/glsl/ast.h | 10 | ||||
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 27 | ||||
-rw-r--r-- | src/glsl/glsl_parser.yy | 12 | ||||
-rw-r--r-- | src/glsl/glsl_parser_extras.cpp | 5 |
4 files changed, 47 insertions, 7 deletions
diff --git a/src/glsl/ast.h b/src/glsl/ast.h index b0430de071e..56e7bd86f91 100644 --- a/src/glsl/ast.h +++ b/src/glsl/ast.h @@ -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 */ }; diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 0b28b4814c4..a57ce5058e1 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -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); diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 83cbb902b5d..ba6bfa1e1fa 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -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: diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index d3339e7795d..f3c5bd04938 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -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 |