diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2011-01-07 18:34:58 -0800 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2011-01-19 10:48:39 -0800 |
commit | 48e81e3b9eb8b880cd702a4ca3237101e3bc6f2d (patch) | |
tree | 302542007ad5462bce0db67c40e9578843696b12 | |
parent | 1785904c5c56d4962a91c3da6c291f418aa45d3c (diff) |
glsl: Track variable usage, use that to enforce semantics
In particular, variables cannot be redeclared invariant after being
used.
Fixes piglit test invariant-05.vert and bugzilla #29164.
NOTE: This is a candidate for the 7.9 and 7.10 branches.
(cherry picked from commit bd33055ef4b6dd18d6247ff7d9e47496ff4acc51)
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 18 | ||||
-rw-r--r-- | src/glsl/ir.cpp | 1 | ||||
-rw-r--r-- | src/glsl/ir.h | 9 |
3 files changed, 26 insertions, 2 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index f1fc6e6ee92..9a9289d00d8 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -1465,6 +1465,7 @@ ast_expression::hir(exec_list *instructions, result = new(ctx) ir_dereference_variable(var); if (var != NULL) { + var->used = true; type = result->type; } else { _mesa_glsl_error(& loc, state, "`%s' undeclared", @@ -1639,8 +1640,16 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, struct _mesa_glsl_parse_state *state, YYLTYPE *loc) { - if (qual->invariant) - var->invariant = 1; + if (qual->invariant) { + if (var->used) { + _mesa_glsl_error(loc, state, + "variable `%s' may not be redeclared " + "`invariant' after being used", + var->name); + } else { + var->invariant = 1; + } + } /* FINISHME: Mark 'in' variables at global scope as read-only. */ if (qual->constant || qual->attribute || qual->uniform @@ -1786,6 +1795,11 @@ ast_declarator_list::hir(exec_list *instructions, _mesa_glsl_error(& loc, state, "`%s' cannot be marked invariant, fragment shader " "inputs only\n", decl->identifier); + } else if (earlier->used) { + _mesa_glsl_error(& loc, state, + "variable `%s' may not be redeclared " + "`invariant' after being used", + earlier->name); } else { earlier->invariant = true; } diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 7064fed8419..919be13290f 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -1124,6 +1124,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->constant_value = NULL; this->origin_upper_left = false; this->pixel_center_integer = false; + this->used = false; if (type && type->base_type == GLSL_TYPE_SAMPLER) this->read_only = true; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 0a520b420ba..e002cc9481a 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -260,6 +260,15 @@ public: unsigned invariant:1; /** + * Has this variable been used for reading or writing? + * + * Several GLSL semantic checks require knowledge of whether or not a + * variable has been used. For example, it is an error to redeclare a + * variable as invariant after it has been used. + */ + unsigned used:1; + + /** * Storage class of the variable. * * \sa ir_variable_mode |