glsl: Refactor AST-to-HIR code handling variable redeclarations

This commit is contained in:
Ian Romanick 2011-03-04 15:28:40 -08:00
parent b0698396dc
commit 8e6cb9fe51

View file

@ -2055,6 +2055,137 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
}
}
/**
* Get the variable that is being redeclared by this declaration
*
* Semantic checks to verify the validity of the redeclaration are also
* performed. If semantic checks fail, compilation error will be emitted via
* \c _mesa_glsl_error, but a non-\c NULL pointer will still be returned.
*
* \returns
* A pointer to an existing variable in the current scope if the declaration
* is a redeclaration, \c NULL otherwise.
*/
ir_variable *
get_variable_being_redeclared(ir_variable *var, ast_declaration *decl,
struct _mesa_glsl_parse_state *state)
{
/* Check if this declaration is actually a re-declaration, either to
* resize an array or add qualifiers to an existing variable.
*
* This is allowed for variables in the current scope, or when at
* global scope (for built-ins in the implicit outer scope).
*/
ir_variable *earlier = state->symbols->get_variable(decl->identifier);
if (earlier == NULL ||
(state->current_function != NULL &&
!state->symbols->name_declared_this_scope(decl->identifier))) {
return NULL;
}
YYLTYPE loc = decl->get_location();
/* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
*
* "It is legal to declare an array without a size and then
* later re-declare the same name as an array of the same
* type and specify a size."
*/
if ((earlier->type->array_size() == 0)
&& var->type->is_array()
&& (var->type->element_type() == earlier->type->element_type())) {
/* FINISHME: This doesn't match the qualifiers on the two
* FINISHME: declarations. It's not 100% clear whether this is
* FINISHME: required or not.
*/
/* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
*
* "The size [of gl_TexCoord] can be at most
* gl_MaxTextureCoords."
*/
const unsigned size = unsigned(var->type->array_size());
if ((strcmp("gl_TexCoord", var->name) == 0)
&& (size > state->Const.MaxTextureCoords)) {
_mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot "
"be larger than gl_MaxTextureCoords (%u)\n",
state->Const.MaxTextureCoords);
} else if ((size > 0) && (size <= earlier->max_array_access)) {
_mesa_glsl_error(& loc, state, "array size must be > %u due to "
"previous access",
earlier->max_array_access);
}
earlier->type = var->type;
delete var;
var = NULL;
} else if (state->ARB_fragment_coord_conventions_enable
&& strcmp(var->name, "gl_FragCoord") == 0
&& earlier->type == var->type
&& earlier->mode == var->mode) {
/* Allow redeclaration of gl_FragCoord for ARB_fcc layout
* qualifiers.
*/
earlier->origin_upper_left = var->origin_upper_left;
earlier->pixel_center_integer = var->pixel_center_integer;
/* According to section 4.3.7 of the GLSL 1.30 spec,
* the following built-in varaibles can be redeclared with an
* interpolation qualifier:
* * gl_FrontColor
* * gl_BackColor
* * gl_FrontSecondaryColor
* * gl_BackSecondaryColor
* * gl_Color
* * gl_SecondaryColor
*/
} else if (state->language_version >= 130
&& (strcmp(var->name, "gl_FrontColor") == 0
|| strcmp(var->name, "gl_BackColor") == 0
|| strcmp(var->name, "gl_FrontSecondaryColor") == 0
|| strcmp(var->name, "gl_BackSecondaryColor") == 0
|| strcmp(var->name, "gl_Color") == 0
|| strcmp(var->name, "gl_SecondaryColor") == 0)
&& earlier->type == var->type
&& earlier->mode == var->mode) {
earlier->interpolation = var->interpolation;
/* Layout qualifiers for gl_FragDepth. */
} else if (state->AMD_conservative_depth_enable
&& strcmp(var->name, "gl_FragDepth") == 0
&& earlier->type == var->type
&& earlier->mode == var->mode) {
/** From the AMD_conservative_depth spec:
* Within any shader, the first redeclarations of gl_FragDepth
* must appear before any use of gl_FragDepth.
*/
if (earlier->used) {
_mesa_glsl_error(&loc, state,
"the first redeclaration of gl_FragDepth "
"must appear before any use of gl_FragDepth");
}
/* Prevent inconsistent redeclaration of depth layout qualifier. */
if (earlier->depth_layout != ir_depth_layout_none
&& earlier->depth_layout != var->depth_layout) {
_mesa_glsl_error(&loc, state,
"gl_FragDepth: depth layout is declared here "
"as '%s, but it was previously declared as "
"'%s'",
depth_layout_string(var->depth_layout),
depth_layout_string(earlier->depth_layout));
}
earlier->depth_layout = var->depth_layout;
} else {
_mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
}
return earlier;
}
ir_rvalue *
ast_declarator_list::hir(exec_list *instructions,
@ -2562,119 +2693,8 @@ ast_declarator_list::hir(exec_list *instructions,
decl->identifier);
}
/* Check if this declaration is actually a re-declaration, either to
* resize an array or add qualifiers to an existing variable.
*
* This is allowed for variables in the current scope, or when at
* global scope (for built-ins in the implicit outer scope).
*/
ir_variable *earlier = state->symbols->get_variable(decl->identifier);
if (earlier != NULL && (state->current_function == NULL ||
state->symbols->name_declared_this_scope(decl->identifier))) {
/* From page 24 (page 30 of the PDF) of the GLSL 1.50 spec,
*
* "It is legal to declare an array without a size and then
* later re-declare the same name as an array of the same
* type and specify a size."
*/
if ((earlier->type->array_size() == 0)
&& var->type->is_array()
&& (var->type->element_type() == earlier->type->element_type())) {
/* FINISHME: This doesn't match the qualifiers on the two
* FINISHME: declarations. It's not 100% clear whether this is
* FINISHME: required or not.
*/
/* From page 54 (page 60 of the PDF) of the GLSL 1.20 spec:
*
* "The size [of gl_TexCoord] can be at most
* gl_MaxTextureCoords."
*/
const unsigned size = unsigned(var->type->array_size());
if ((strcmp("gl_TexCoord", var->name) == 0)
&& (size > state->Const.MaxTextureCoords)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state, "`gl_TexCoord' array size cannot "
"be larger than gl_MaxTextureCoords (%u)\n",
state->Const.MaxTextureCoords);
} else if ((size > 0) && (size <= earlier->max_array_access)) {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(& loc, state, "array size must be > %u due to "
"previous access",
earlier->max_array_access);
}
earlier->type = var->type;
delete var;
var = NULL;
} else if (state->ARB_fragment_coord_conventions_enable
&& strcmp(var->name, "gl_FragCoord") == 0
&& earlier->type == var->type
&& earlier->mode == var->mode) {
/* Allow redeclaration of gl_FragCoord for ARB_fcc layout
* qualifiers.
*/
earlier->origin_upper_left = var->origin_upper_left;
earlier->pixel_center_integer = var->pixel_center_integer;
/* According to section 4.3.7 of the GLSL 1.30 spec,
* the following built-in varaibles can be redeclared with an
* interpolation qualifier:
* * gl_FrontColor
* * gl_BackColor
* * gl_FrontSecondaryColor
* * gl_BackSecondaryColor
* * gl_Color
* * gl_SecondaryColor
*/
} else if (state->language_version >= 130
&& (strcmp(var->name, "gl_FrontColor") == 0
|| strcmp(var->name, "gl_BackColor") == 0
|| strcmp(var->name, "gl_FrontSecondaryColor") == 0
|| strcmp(var->name, "gl_BackSecondaryColor") == 0
|| strcmp(var->name, "gl_Color") == 0
|| strcmp(var->name, "gl_SecondaryColor") == 0)
&& earlier->type == var->type
&& earlier->mode == var->mode) {
earlier->interpolation = var->interpolation;
/* Layout qualifiers for gl_FragDepth. */
} else if (state->AMD_conservative_depth_enable
&& strcmp(var->name, "gl_FragDepth") == 0
&& earlier->type == var->type
&& earlier->mode == var->mode) {
/** From the AMD_conservative_depth spec:
* Within any shader, the first redeclarations of gl_FragDepth
* must appear before any use of gl_FragDepth.
*/
if (earlier->used) {
_mesa_glsl_error(&loc, state,
"the first redeclaration of gl_FragDepth "
"must appear before any use of gl_FragDepth");
}
/* Prevent inconsistent redeclaration of depth layout qualifier. */
if (earlier->depth_layout != ir_depth_layout_none
&& earlier->depth_layout != var->depth_layout) {
_mesa_glsl_error(&loc, state,
"gl_FragDepth: depth layout is declared here "
"as '%s, but it was previously declared as "
"'%s'",
depth_layout_string(var->depth_layout),
depth_layout_string(earlier->depth_layout));
}
earlier->depth_layout = var->depth_layout;
} else {
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state, "`%s' redeclared", decl->identifier);
}
ir_variable *earlier = get_variable_being_redeclared(var, decl, state);
if (earlier != NULL) {
continue;
}