glsl: Refactor AST-to-HIR code handling variable redeclarations
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 4 Mar 2011 23:28:40 +0000 (15:28 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Sat, 5 Mar 2011 00:32:37 +0000 (16:32 -0800)
src/glsl/ast_to_hir.cpp

index fd1f0b49f42de2a3ca25de611f6fb60c910ae192..8864279e5d633bc817551334f6c9a76d3cfdd5ae 100644 (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;
       }