diff options
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 246 |
1 files changed, 133 insertions, 113 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index fd1f0b49f42..8864279e5d6 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -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; } |