linker: Check that initializers for global variables match

This requires tracking a couple extra fields in ir_variable:

 * A flag to indicate that a variable had an initializer.

 * For non-const variables, a field to track the constant value of the
   variable's initializer.

For variables non-constant initalizers, ir_variable::has_initializer
will be true, but ir_variable::constant_initializer will be NULL.  The
linker can use the values of these fields to check adherence to the
GLSL 4.20 rules for shared global variables:

    "If a shared global has multiple initializers, the initializers
    must all be constant expressions, and they must all have the same
    value. Otherwise, a link error will result. (A shared global
    having only one initializer does not require that initializer to
    be a constant expression.)"

Previous to 4.20 the GLSL spec simply said that initializers must have
the same value.  In this case of non-constant initializers, this was
impossible to determine.  As a result, no vendor actually implemented
that behavior.  The 4.20 behavior matches the behavior of NVIDIA's
shipping implementations.

NOTE: This is candidate for the 7.11 branch.  This patch also needs
the preceding patch "glsl: Refactor generate_ARB_draw_buffers_variables
to use add_builtin_constant"

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=34687
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Acked-by: Paul Berry <stereotype441@gmail.com>
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index a595c9c..915d5bb 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -448,17 +448,30 @@
 	       }
 	    }
 
-	    /* FINISHME: Handle non-constant initializers.
+	    /* Page 35 (page 41 of the PDF) of the GLSL 4.20 spec says:
+	     *
+	     *     "If a shared global has multiple initializers, the
+	     *     initializers must all be constant expressions, and they
+	     *     must all have the same value. Otherwise, a link error will
+	     *     result. (A shared global having only one initializer does
+	     *     not require that initializer to be a constant expression.)"
+	     *
+	     * Previous to 4.20 the GLSL spec simply said that initializers
+	     * must have the same value.  In this case of non-constant
+	     * initializers, this was impossible to determine.  As a result,
+	     * no vendor actually implemented that behavior.  The 4.20
+	     * behavior matches the implemented behavior of at least one other
+	     * vendor, so we'll implement that for all GLSL versions.
 	     */
-	    if (var->constant_value != NULL) {
-	       if (existing->constant_value != NULL) {
-		  if (!var->constant_value->has_value(existing->constant_value)) {
+	    if (var->constant_initializer != NULL) {
+	       if (existing->constant_initializer != NULL) {
+		  if (!var->constant_initializer->has_value(existing->constant_initializer)) {
 		     linker_error(prog, "initializers for %s "
 				  "`%s' have differing values\n",
 				  mode_string(var), var->name);
 		     return false;
 		  }
-	       } else
+	       } else {
 		  /* If the first-seen instance of a particular uniform did not
 		   * have an initializer but a later instance does, copy the
 		   * initializer to the version stored in the symbol table.
@@ -471,8 +484,29 @@
 		   * FINISHME: modify the shader, and linking with the second
 		   * FINISHME: will fail.
 		   */
-		  existing->constant_value =
-		     var->constant_value->clone(ralloc_parent(existing), NULL);
+		  existing->constant_initializer =
+		     var->constant_initializer->clone(ralloc_parent(existing),
+						      NULL);
+	       }
+	    }
+
+	    if (var->has_initializer) {
+	       if (existing->has_initializer
+		   && (var->constant_initializer == NULL
+		       || existing->constant_initializer == NULL)) {
+		  linker_error(prog,
+			       "shared global variable `%s' has multiple "
+			       "non-constant initializers.\n",
+			       var->name);
+		  return false;
+	       }
+
+	       /* Some instance had an initializer, so keep track of that.  In
+		* this location, all sorts of initializers (constant or
+		* otherwise) will propagate the existence to the variable
+		* stored in the symbol table.
+		*/
+	       existing->has_initializer = true;
 	    }
 
 	    if (existing->invariant != var->invariant) {