summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2011-01-07 18:34:58 -0800
committerIan Romanick <ian.d.romanick@intel.com>2011-01-19 10:48:39 -0800
commit48e81e3b9eb8b880cd702a4ca3237101e3bc6f2d (patch)
tree302542007ad5462bce0db67c40e9578843696b12
parent1785904c5c56d4962a91c3da6c291f418aa45d3c (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.cpp18
-rw-r--r--src/glsl/ir.cpp1
-rw-r--r--src/glsl/ir.h9
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