mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 11:20: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 *
|
ir_rvalue *
|
||||||
ast_declarator_list::hir(exec_list *instructions,
|
ast_declarator_list::hir(exec_list *instructions,
|
||||||
|
|
@ -2562,119 +2693,8 @@ ast_declarator_list::hir(exec_list *instructions,
|
||||||
decl->identifier);
|
decl->identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this declaration is actually a re-declaration, either to
|
ir_variable *earlier = get_variable_being_redeclared(var, decl, state);
|
||||||
* resize an array or add qualifiers to an existing variable.
|
if (earlier != NULL) {
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue