mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 04:50:11 +01:00
glsl: Refactor AST-to-HIR code handling variable redeclarations
This commit is contained in:
parent
b0698396dc
commit
8e6cb9fe51
1 changed files with 133 additions and 113 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue