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.
This commit is contained in:
@@ -1623,6 +1623,7 @@ ast_expression::hir(exec_list *instructions,
|
|||||||
result = new(ctx) ir_dereference_variable(var);
|
result = new(ctx) ir_dereference_variable(var);
|
||||||
|
|
||||||
if (var != NULL) {
|
if (var != NULL) {
|
||||||
|
var->used = true;
|
||||||
type = result->type;
|
type = result->type;
|
||||||
} else {
|
} else {
|
||||||
_mesa_glsl_error(& loc, state, "`%s' undeclared",
|
_mesa_glsl_error(& loc, state, "`%s' undeclared",
|
||||||
@@ -1797,8 +1798,16 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
|
|||||||
struct _mesa_glsl_parse_state *state,
|
struct _mesa_glsl_parse_state *state,
|
||||||
YYLTYPE *loc)
|
YYLTYPE *loc)
|
||||||
{
|
{
|
||||||
if (qual->flags.q.invariant)
|
if (qual->flags.q.invariant) {
|
||||||
var->invariant = 1;
|
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. */
|
/* FINISHME: Mark 'in' variables at global scope as read-only. */
|
||||||
if (qual->flags.q.constant || qual->flags.q.attribute
|
if (qual->flags.q.constant || qual->flags.q.attribute
|
||||||
@@ -2005,6 +2014,11 @@ ast_declarator_list::hir(exec_list *instructions,
|
|||||||
_mesa_glsl_error(& loc, state,
|
_mesa_glsl_error(& loc, state,
|
||||||
"`%s' cannot be marked invariant, fragment shader "
|
"`%s' cannot be marked invariant, fragment shader "
|
||||||
"inputs only\n", decl->identifier);
|
"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 {
|
} else {
|
||||||
earlier->invariant = true;
|
earlier->invariant = true;
|
||||||
}
|
}
|
||||||
|
@@ -1325,6 +1325,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
|
|||||||
this->constant_value = NULL;
|
this->constant_value = NULL;
|
||||||
this->origin_upper_left = false;
|
this->origin_upper_left = false;
|
||||||
this->pixel_center_integer = false;
|
this->pixel_center_integer = false;
|
||||||
|
this->used = false;
|
||||||
|
|
||||||
if (type && type->base_type == GLSL_TYPE_SAMPLER)
|
if (type && type->base_type == GLSL_TYPE_SAMPLER)
|
||||||
this->read_only = true;
|
this->read_only = true;
|
||||||
|
@@ -294,6 +294,15 @@ public:
|
|||||||
unsigned centroid:1;
|
unsigned centroid:1;
|
||||||
unsigned invariant:1;
|
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.
|
* Storage class of the variable.
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user