summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2011-03-04 15:28:40 -0800
committerIan Romanick <ian.d.romanick@intel.com>2011-03-04 16:32:37 -0800
commit8e6cb9fe51a2237e51b47198eb7d46b14ad288b5 (patch)
tree354b11bc9eeec066762c9b5c4be795b2d936fd43
parentb0698396dcc70f6c8a16090dfb1674996538db3a (diff)
glsl: Refactor AST-to-HIR code handling variable redeclarations
-rw-r--r--src/glsl/ast_to_hir.cpp246
1 files changed, 133 insertions, 113 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index fd1f0b49f4..8864279e5d 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;
}