r600g: fix error path and use util_slab_free
[mesa.git] / src / glsl / linker.cpp
index bddf8788b47a3f01d03f91040ca43511d5a10dd2..35270881af5960d9e2d3bae6adcf16385285af93 100644 (file)
  *
  * \author Ian Romanick <ian.d.romanick@intel.com>
  */
-#include <cstdlib>
-#include <cstdio>
-#include <cstdarg>
-#include <climits>
-
-extern "C" {
-#include <talloc.h>
-}
 
 #include "main/core.h"
 #include "glsl_symbol_table.h"
@@ -80,6 +72,10 @@ extern "C" {
 #include "linker.h"
 #include "ir_optimization.h"
 
+extern "C" {
+#include "main/shaderobj.h"
+}
+
 /**
  * Visitor that determines whether or not a variable is ever written.
  */
@@ -168,20 +164,35 @@ private:
 
 
 void
-linker_error_printf(gl_shader_program *prog, const char *fmt, ...)
+linker_error(gl_shader_program *prog, const char *fmt, ...)
 {
    va_list ap;
 
-   prog->InfoLog = talloc_strdup_append(prog->InfoLog, "error: ");
+   ralloc_strcat(&prog->InfoLog, "error: ");
    va_start(ap, fmt);
-   prog->InfoLog = talloc_vasprintf_append(prog->InfoLog, fmt, ap);
+   ralloc_vasprintf_append(&prog->InfoLog, fmt, ap);
    va_end(ap);
+
+   prog->LinkStatus = false;
 }
 
 
 void
-invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
-                             int generic_base)
+linker_warning(gl_shader_program *prog, const char *fmt, ...)
+{
+   va_list ap;
+
+   ralloc_strcat(&prog->InfoLog, "error: ");
+   va_start(ap, fmt);
+   ralloc_vasprintf_append(&prog->InfoLog, fmt, ap);
+   va_end(ap);
+
+}
+
+
+void
+link_invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
+                                  int generic_base)
 {
    foreach_list(node, sh->ir) {
       ir_variable *const var = ((ir_instruction *) node)->as_variable();
@@ -191,7 +202,7 @@ invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
 
       /* Only assign locations for generic attributes / varyings / etc.
        */
-      if (var->location >= generic_base)
+      if ((var->location >= generic_base) && !var->explicit_location)
          var->location = -1;
    }
 }
@@ -233,7 +244,9 @@ count_attribute_slots(const glsl_type *t)
 
 
 /**
- * Verify that a vertex shader executable meets all semantic requirements
+ * Verify that a vertex shader executable meets all semantic requirements.
+ *
+ * Also sets prog->Vert.UsesClipDistance as a side effect.
  *
  * \param shader  Vertex shader executable to be verified
  */
@@ -247,11 +260,30 @@ validate_vertex_shader_executable(struct gl_shader_program *prog,
    find_assignment_visitor find("gl_Position");
    find.run(shader->ir);
    if (!find.variable_found()) {
-      linker_error_printf(prog,
-                         "vertex shader does not write to `gl_Position'\n");
+      linker_error(prog, "vertex shader does not write to `gl_Position'\n");
       return false;
    }
 
+   if (prog->Version >= 130) {
+      /* From section 7.1 (Vertex Shader Special Variables) of the
+       * GLSL 1.30 spec:
+       *
+       *   "It is an error for a shader to statically write both
+       *   gl_ClipVertex and gl_ClipDistance."
+       */
+      find_assignment_visitor clip_vertex("gl_ClipVertex");
+      find_assignment_visitor clip_distance("gl_ClipDistance");
+
+      clip_vertex.run(shader->ir);
+      clip_distance.run(shader->ir);
+      if (clip_vertex.variable_found() && clip_distance.variable_found()) {
+         linker_error(prog, "vertex shader writes to both `gl_ClipVertex' "
+                      "and `gl_ClipDistance'\n");
+         return false;
+      }
+      prog->Vert.UsesClipDistance = clip_distance.variable_found();
+   }
+
    return true;
 }
 
@@ -275,8 +307,8 @@ validate_fragment_shader_executable(struct gl_shader_program *prog,
    frag_data.run(shader->ir);
 
    if (frag_color.variable_found() && frag_data.variable_found()) {
-      linker_error_printf(prog,  "fragment shader writes to both "
-                         "`gl_FragColor' and `gl_FragData'\n");
+      linker_error(prog,  "fragment shader writes to both "
+                  "`gl_FragColor' and `gl_FragData'\n");
       return false;
    }
 
@@ -299,6 +331,7 @@ mode_string(const ir_variable *var)
    case ir_var_out:     return "shader output";
    case ir_var_inout:   return "shader inout";
 
+   case ir_var_const_in:
    case ir_var_temporary:
    default:
       assert(!"Should not get here.");
@@ -321,6 +354,9 @@ cross_validate_globals(struct gl_shader_program *prog,
     */
    glsl_symbol_table variables;
    for (unsigned i = 0; i < num_shaders; i++) {
+      if (shader_list[i] == NULL)
+        continue;
+
       foreach_list(node, shader_list[i]->ir) {
         ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
@@ -353,29 +389,89 @@ cross_validate_globals(struct gl_shader_program *prog,
                   && (var->type->fields.array == existing->type->fields.array)
                   && ((var->type->length == 0)
                       || (existing->type->length == 0))) {
-                 if (existing->type->length == 0)
+                 if (var->type->length != 0) {
                     existing->type = var->type;
+                 }
               } else {
-                 linker_error_printf(prog, "%s `%s' declared as type "
-                                     "`%s' and type `%s'\n",
-                                     mode_string(var),
-                                     var->name, var->type->name,
-                                     existing->type->name);
+                 linker_error(prog, "%s `%s' declared as type "
+                              "`%s' and type `%s'\n",
+                              mode_string(var),
+                              var->name, var->type->name,
+                              existing->type->name);
                  return false;
               }
            }
 
-           /* FINISHME: Handle non-constant initializers.
+           if (var->explicit_location) {
+              if (existing->explicit_location
+                  && (var->location != existing->location)) {
+                    linker_error(prog, "explicit locations for %s "
+                                 "`%s' have differing values\n",
+                                 mode_string(var), var->name);
+                    return false;
+              }
+
+              existing->location = var->location;
+              existing->explicit_location = true;
+           }
+
+           /* Validate layout qualifiers for gl_FragDepth.
+            *
+            * From the AMD/ARB_conservative_depth specs:
+            *
+            *    "If gl_FragDepth is redeclared in any fragment shader in a
+            *    program, it must be redeclared in all fragment shaders in
+            *    that program that have static assignments to
+            *    gl_FragDepth. All redeclarations of gl_FragDepth in all
+            *    fragment shaders in a single program must have the same set
+            *    of qualifiers."
+            */
+           if (strcmp(var->name, "gl_FragDepth") == 0) {
+              bool layout_declared = var->depth_layout != ir_depth_layout_none;
+              bool layout_differs =
+                 var->depth_layout != existing->depth_layout;
+
+              if (layout_declared && layout_differs) {
+                 linker_error(prog,
+                              "All redeclarations of gl_FragDepth in all "
+                              "fragment shaders in a single program must have "
+                              "the same set of qualifiers.");
+              }
+
+              if (var->used && layout_differs) {
+                 linker_error(prog,
+                              "If gl_FragDepth is redeclared with a layout "
+                              "qualifier in any fragment shader, it must be "
+                              "redeclared with the same layout qualifier in "
+                              "all fragment shaders that have assignments to "
+                              "gl_FragDepth");
+              }
+           }
+
+           /* 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)) {
-                    linker_error_printf(prog, "initializers for %s "
-                                        "`%s' have differing values\n",
-                                        mode_string(var), var->name);
+           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.
@@ -388,11 +484,45 @@ cross_validate_globals(struct gl_shader_program *prog,
                   * FINISHME: modify the shader, and linking with the second
                   * FINISHME: will fail.
                   */
-                 existing->constant_value =
-                    var->constant_value->clone(talloc_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) {
+              linker_error(prog, "declarations for %s `%s' have "
+                           "mismatching invariant qualifiers\n",
+                           mode_string(var), var->name);
+              return false;
+           }
+            if (existing->centroid != var->centroid) {
+               linker_error(prog, "declarations for %s `%s' have "
+                           "mismatching centroid qualifiers\n",
+                           mode_string(var), var->name);
+               return false;
+            }
         } else
-           variables.add_variable(var->name, var);
+           variables.add_variable(var);
       }
    }
 
@@ -407,7 +537,7 @@ bool
 cross_validate_uniforms(struct gl_shader_program *prog)
 {
    return cross_validate_globals(prog, prog->_LinkedShaders,
-                                prog->_NumLinkedShaders, true);
+                                MESA_SHADER_TYPES, true);
 }
 
 
@@ -434,7 +564,7 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
       if ((var == NULL) || (var->mode != ir_var_out))
         continue;
 
-      parameters.add_variable(var->name, var);
+      parameters.add_variable(var);
    }
 
 
@@ -456,53 +586,73 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
         /* Check that the types match between stages.
          */
         if (input->type != output->type) {
-           linker_error_printf(prog,
-                               "%s shader output `%s' declared as "
-                               "type `%s', but %s shader input declared "
-                               "as type `%s'\n",
-                               producer_stage, output->name,
-                               output->type->name,
-                               consumer_stage, input->type->name);
-           return false;
+           /* There is a bit of a special case for gl_TexCoord.  This
+            * built-in is unsized by default.  Applications that variable
+            * access it must redeclare it with a size.  There is some
+            * language in the GLSL spec that implies the fragment shader
+            * and vertex shader do not have to agree on this size.  Other
+            * driver behave this way, and one or two applications seem to
+            * rely on it.
+            *
+            * Neither declaration needs to be modified here because the array
+            * sizes are fixed later when update_array_sizes is called.
+            *
+            * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec:
+            *
+            *     "Unlike user-defined varying variables, the built-in
+            *     varying variables don't have a strict one-to-one
+            *     correspondence between the vertex language and the
+            *     fragment language."
+            */
+           if (!output->type->is_array()
+               || (strncmp("gl_", output->name, 3) != 0)) {
+              linker_error(prog,
+                           "%s shader output `%s' declared as type `%s', "
+                           "but %s shader input declared as type `%s'\n",
+                           producer_stage, output->name,
+                           output->type->name,
+                           consumer_stage, input->type->name);
+              return false;
+           }
         }
 
         /* Check that all of the qualifiers match between stages.
          */
         if (input->centroid != output->centroid) {
-           linker_error_printf(prog,
-                               "%s shader output `%s' %s centroid qualifier, "
-                               "but %s shader input %s centroid qualifier\n",
-                               producer_stage,
-                               output->name,
-                               (output->centroid) ? "has" : "lacks",
-                               consumer_stage,
-                               (input->centroid) ? "has" : "lacks");
+           linker_error(prog,
+                        "%s shader output `%s' %s centroid qualifier, "
+                        "but %s shader input %s centroid qualifier\n",
+                        producer_stage,
+                        output->name,
+                        (output->centroid) ? "has" : "lacks",
+                        consumer_stage,
+                        (input->centroid) ? "has" : "lacks");
            return false;
         }
 
         if (input->invariant != output->invariant) {
-           linker_error_printf(prog,
-                               "%s shader output `%s' %s invariant qualifier, "
-                               "but %s shader input %s invariant qualifier\n",
-                               producer_stage,
-                               output->name,
-                               (output->invariant) ? "has" : "lacks",
-                               consumer_stage,
-                               (input->invariant) ? "has" : "lacks");
+           linker_error(prog,
+                        "%s shader output `%s' %s invariant qualifier, "
+                        "but %s shader input %s invariant qualifier\n",
+                        producer_stage,
+                        output->name,
+                        (output->invariant) ? "has" : "lacks",
+                        consumer_stage,
+                        (input->invariant) ? "has" : "lacks");
            return false;
         }
 
         if (input->interpolation != output->interpolation) {
-           linker_error_printf(prog,
-                               "%s shader output `%s' specifies %s "
-                               "interpolation qualifier, "
-                               "but %s shader input specifies %s "
-                               "interpolation qualifier\n",
-                               producer_stage,
-                               output->name,
-                               output->interpolation_string(),
-                               consumer_stage,
-                               input->interpolation_string());
+           linker_error(prog,
+                        "%s shader output `%s' specifies %s "
+                        "interpolation qualifier, "
+                        "but %s shader input specifies %s "
+                        "interpolation qualifier\n",
+                        producer_stage,
+                        output->name,
+                        output->interpolation_string(),
+                        consumer_stage,
+                        input->interpolation_string());
            return false;
         }
       }
@@ -526,9 +676,9 @@ populate_symbol_table(gl_shader *sh)
       ir_function *func;
 
       if ((func = inst->as_function()) != NULL) {
-        sh->symbols->add_function(func->name, func);
+        sh->symbols->add_function(func);
       } else if ((var = inst->as_variable()) != NULL) {
-        sh->symbols->add_variable(var->name, var);
+        sh->symbols->add_variable(var);
       }
    }
 }
@@ -585,7 +735,7 @@ remap_variables(ir_instruction *inst, struct gl_shader *target,
         else {
            ir_variable *copy = ir->var->clone(this->target, NULL);
 
-           this->symbols->add_variable(copy->name, copy);
+           this->symbols->add_variable(copy);
            this->instructions->push_head(copy);
            ir->var = copy;
         }
@@ -706,7 +856,8 @@ get_main_function_signature(gl_shader *sh)
  * shader is returned.
  */
 static struct gl_shader *
-link_intrastage_shaders(GLcontext *ctx,
+link_intrastage_shaders(void *mem_ctx,
+                       struct gl_context *ctx,
                        struct gl_shader_program *prog,
                        struct gl_shader **shader_list,
                        unsigned num_shaders)
@@ -748,9 +899,8 @@ link_intrastage_shaders(GLcontext *ctx,
 
               if ((other_sig != NULL) && other_sig->is_defined
                   && !other_sig->is_builtin) {
-                 linker_error_printf(prog,
-                                     "function `%s' is multiply defined",
-                                     f->name);
+                 linker_error(prog, "function `%s' is multiply defined",
+                              f->name);
                  return NULL;
               }
            }
@@ -774,15 +924,15 @@ link_intrastage_shaders(GLcontext *ctx,
    }
 
    if (main == NULL) {
-      linker_error_printf(prog, "%s shader lacks `main'\n",
-                         (shader_list[0]->Type == GL_VERTEX_SHADER)
-                         ? "vertex" : "fragment");
+      linker_error(prog, "%s shader lacks `main'\n",
+                  (shader_list[0]->Type == GL_VERTEX_SHADER)
+                  ? "vertex" : "fragment");
       return NULL;
    }
 
-   gl_shader *const linked = ctx->Driver.NewShader(NULL, 0, main->Type);
+   gl_shader *linked = ctx->Driver.NewShader(NULL, 0, main->Type);
    linked->ir = new(linked) exec_list;
-   clone_ir_list(linked, linked->ir, main->ir);
+   clone_ir_list(mem_ctx, linked->ir, main->ir);
 
    populate_symbol_table(linked);
 
@@ -827,19 +977,49 @@ link_intrastage_shaders(GLcontext *ctx,
 
    assert(idx == num_linking_shaders);
 
-   link_function_calls(prog, linked, linking_shaders, num_linking_shaders);
+   if (!link_function_calls(prog, linked, linking_shaders,
+                           num_linking_shaders)) {
+      ctx->Driver.DeleteShader(ctx, linked);
+      linked = NULL;
+   }
 
    free(linking_shaders);
 
-   return linked;
-}
+#ifdef DEBUG
+   /* At this point linked should contain all of the linked IR, so
+    * validate it to make sure nothing went wrong.
+    */
+   if (linked)
+      validate_ir_tree(linked->ir);
+#endif
 
+   /* Make a pass over all variable declarations to ensure that arrays with
+    * unspecified sizes have a size specified.  The size is inferred from the
+    * max_array_access field.
+    */
+   if (linked != NULL) {
+      class array_sizing_visitor : public ir_hierarchical_visitor {
+      public:
+        virtual ir_visitor_status visit(ir_variable *var)
+        {
+           if (var->type->is_array() && (var->type->length == 0)) {
+              const glsl_type *type =
+                 glsl_type::get_array_instance(var->type->fields.array,
+                                               var->max_array_access + 1);
+
+              assert(type != NULL);
+              var->type = type;
+           }
 
-struct uniform_node {
-   exec_node link;
-   struct gl_uniform *u;
-   unsigned slots;
-};
+           return visit_continue;
+        }
+      } v;
+
+      v.run(linked->ir);
+   }
+
+   return linked;
+}
 
 /**
  * Update the sizes of linked shader uniform arrays to the maximum
@@ -859,7 +1039,10 @@ struct uniform_node {
 static void
 update_array_sizes(struct gl_shader_program *prog)
 {
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+        if (prog->_LinkedShaders[i] == NULL)
+           continue;
+
       foreach_list(node, prog->_LinkedShaders[i]->ir) {
         ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
@@ -870,7 +1053,10 @@ update_array_sizes(struct gl_shader_program *prog)
            continue;
 
         unsigned int size = var->max_array_access;
-        for (unsigned j = 0; j < prog->_NumLinkedShaders; j++) {
+        for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
+              if (prog->_LinkedShaders[j] == NULL)
+                 continue;
+
            foreach_list(node2, prog->_LinkedShaders[j]->ir) {
               ir_variable *other_var = ((ir_instruction *) node2)->as_variable();
               if (!other_var)
@@ -884,6 +1070,19 @@ update_array_sizes(struct gl_shader_program *prog)
         }
 
         if (size + 1 != var->type->fields.array->length) {
+           /* If this is a built-in uniform (i.e., it's backed by some
+            * fixed-function state), adjust the number of state slots to
+            * match the new array size.  The number of slots per array entry
+            * is not known.  It seems safe to assume that the total number of
+            * slots is an integer multiple of the number of array elements.
+            * Determine the number of slots per array element by dividing by
+            * the old (total) size.
+            */
+           if (var->num_state_slots > 0) {
+              var->num_state_slots = (size + 1)
+                 * (var->num_state_slots / var->type->length);
+           }
+
            var->type = glsl_type::get_array_instance(var->type->fields.array,
                                                      size + 1);
            /* FINISHME: We should update the types of array
@@ -894,150 +1093,8 @@ update_array_sizes(struct gl_shader_program *prog)
    }
 }
 
-static void
-add_uniform(void *mem_ctx, exec_list *uniforms, struct hash_table *ht,
-           const char *name, const glsl_type *type, GLenum shader_type,
-           unsigned *next_shader_pos, unsigned *total_uniforms)
-{
-   if (type->is_record()) {
-      for (unsigned int i = 0; i < type->length; i++) {
-        const glsl_type *field_type = type->fields.structure[i].type;
-        char *field_name = talloc_asprintf(mem_ctx, "%s.%s", name,
-                                           type->fields.structure[i].name);
-
-        add_uniform(mem_ctx, uniforms, ht, field_name, field_type,
-                    shader_type, next_shader_pos, total_uniforms);
-      }
-   } else {
-      uniform_node *n = (uniform_node *) hash_table_find(ht, name);
-      unsigned int vec4_slots;
-      const glsl_type *array_elem_type = NULL;
-
-      if (type->is_array()) {
-        array_elem_type = type->fields.array;
-        /* Array of structures. */
-        if (array_elem_type->is_record()) {
-           for (unsigned int i = 0; i < type->length; i++) {
-              char *elem_name = talloc_asprintf(mem_ctx, "%s[%d]", name, i);
-              add_uniform(mem_ctx, uniforms, ht, elem_name, array_elem_type,
-                          shader_type, next_shader_pos, total_uniforms);
-           }
-           return;
-        }
-      }
-
-      /* Fix the storage size of samplers at 1 vec4 each. Be sure to pad out
-       * vectors to vec4 slots.
-       */
-      if (type->is_array()) {
-        if (array_elem_type->is_sampler())
-           vec4_slots = type->length;
-        else
-           vec4_slots = type->length * array_elem_type->matrix_columns;
-      } else if (type->is_sampler()) {
-        vec4_slots = 1;
-      } else {
-        vec4_slots = type->matrix_columns;
-      }
-
-      if (n == NULL) {
-        n = (uniform_node *) calloc(1, sizeof(struct uniform_node));
-        n->u = (gl_uniform *) calloc(1, sizeof(struct gl_uniform));
-        n->slots = vec4_slots;
-
-        n->u->Name = strdup(name);
-        n->u->Type = type;
-        n->u->VertPos = -1;
-        n->u->FragPos = -1;
-        n->u->GeomPos = -1;
-        (*total_uniforms)++;
-
-        hash_table_insert(ht, n, name);
-        uniforms->push_tail(& n->link);
-      }
-
-      switch (shader_type) {
-      case GL_VERTEX_SHADER:
-        n->u->VertPos = *next_shader_pos;
-        break;
-      case GL_FRAGMENT_SHADER:
-        n->u->FragPos = *next_shader_pos;
-        break;
-      case GL_GEOMETRY_SHADER:
-        n->u->GeomPos = *next_shader_pos;
-        break;
-      }
-
-      (*next_shader_pos) += vec4_slots;
-   }
-}
-
-void
-assign_uniform_locations(struct gl_shader_program *prog)
-{
-   /* */
-   exec_list uniforms;
-   unsigned total_uniforms = 0;
-   hash_table *ht = hash_table_ctor(32, hash_table_string_hash,
-                                   hash_table_string_compare);
-   void *mem_ctx = talloc_new(NULL);
-
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
-      unsigned next_position = 0;
-
-      foreach_list(node, prog->_LinkedShaders[i]->ir) {
-        ir_variable *const var = ((ir_instruction *) node)->as_variable();
-
-        if ((var == NULL) || (var->mode != ir_var_uniform))
-           continue;
-
-        if (strncmp(var->name, "gl_", 3) == 0) {
-           /* At the moment, we don't allocate uniform locations for
-            * builtin uniforms.  It's permitted by spec, and we'll
-            * likely switch to doing that at some point, but not yet.
-            */
-           continue;
-        }
-
-        var->location = next_position;
-        add_uniform(mem_ctx, &uniforms, ht, var->name, var->type,
-                    prog->_LinkedShaders[i]->Type,
-                    &next_position, &total_uniforms);
-      }
-   }
-
-   talloc_free(mem_ctx);
-
-   gl_uniform_list *ul = (gl_uniform_list *)
-      calloc(1, sizeof(gl_uniform_list));
-
-   ul->Size = total_uniforms;
-   ul->NumUniforms = total_uniforms;
-   ul->Uniforms = (gl_uniform *) calloc(total_uniforms, sizeof(gl_uniform));
-
-   unsigned idx = 0;
-   uniform_node *next;
-   for (uniform_node *node = (uniform_node *) uniforms.head
-          ; node->link.next != NULL
-          ; node = next) {
-      next = (uniform_node *) node->link.next;
-
-      node->link.remove();
-      memcpy(&ul->Uniforms[idx], node->u, sizeof(gl_uniform));
-      idx++;
-
-      free(node->u);
-      free(node);
-   }
-
-   hash_table_dtor(ht);
-
-   prog->Uniforms = ul;
-}
-
-
 /**
- * Find a contiguous set of available bits in a bitmask
+ * Find a contiguous set of available bits in a bitmask.
  *
  * \param used_mask     Bits representing used (1) and unused (0) locations
  * \param needed_count  Number of contiguous bits needed.
@@ -1068,23 +1125,45 @@ find_available_slots(unsigned used_mask, unsigned needed_count)
 }
 
 
+/**
+ * Assign locations for either VS inputs for FS outputs
+ *
+ * \param prog          Shader program whose variables need locations assigned
+ * \param target_index  Selector for the program target to receive location
+ *                      assignmnets.  Must be either \c MESA_SHADER_VERTEX or
+ *                      \c MESA_SHADER_FRAGMENT.
+ * \param max_index     Maximum number of generic locations.  This corresponds
+ *                      to either the maximum number of draw buffers or the
+ *                      maximum number of generic attributes.
+ *
+ * \return
+ * If locations are successfully assigned, true is returned.  Otherwise an
+ * error is emitted to the shader link log and false is returned.
+ */
 bool
-assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index)
+assign_attribute_or_color_locations(gl_shader_program *prog,
+                                   unsigned target_index,
+                                   unsigned max_index)
 {
-   /* Mark invalid attribute locations as being used.
+   /* Mark invalid locations as being used.
     */
-   unsigned used_locations = (max_attribute_index >= 32)
-      ? ~0 : ~((1 << max_attribute_index) - 1);
+   unsigned used_locations = (max_index >= 32)
+      ? ~0 : ~((1 << max_index) - 1);
 
-   gl_shader *const sh = prog->_LinkedShaders[0];
-   assert(sh->Type == GL_VERTEX_SHADER);
+   assert((target_index == MESA_SHADER_VERTEX)
+         || (target_index == MESA_SHADER_FRAGMENT));
+
+   gl_shader *const sh = prog->_LinkedShaders[target_index];
+   if (sh == NULL)
+      return true;
 
    /* Operate in a total of four passes.
     *
     * 1. Invalidate the location assignments for all vertex shader inputs.
     *
     * 2. Assign locations for inputs that have user-defined (via
-    *    glBindVertexAttribLocation) locatoins.
+    *    glBindVertexAttribLocation) locations and outputs that have
+    *    user-defined locations (via glBindFragDataLocation).
     *
     * 3. Sort the attributes without assigned locations by number of slots
     *    required in decreasing order.  Fragmentation caused by attribute
@@ -1094,72 +1173,14 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
     * 4. Assign locations to any inputs without assigned locations.
     */
 
-   invalidate_variable_locations(sh, ir_var_in, VERT_ATTRIB_GENERIC0);
+   const int generic_base = (target_index == MESA_SHADER_VERTEX)
+      ? (int) VERT_ATTRIB_GENERIC0 : (int) FRAG_RESULT_DATA0;
 
-   if (prog->Attributes != NULL) {
-      for (unsigned i = 0; i < prog->Attributes->NumParameters; i++) {
-        ir_variable *const var =
-           sh->symbols->get_variable(prog->Attributes->Parameters[i].Name);
+   const enum ir_variable_mode direction =
+      (target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out;
 
-        /* Note: attributes that occupy multiple slots, such as arrays or
-         * matrices, may appear in the attrib array multiple times.
-         */
-        if ((var == NULL) || (var->location != -1))
-           continue;
 
-        /* From page 61 of the OpenGL 4.0 spec:
-         *
-         *     "LinkProgram will fail if the attribute bindings assigned by
-         *     BindAttribLocation do not leave not enough space to assign a
-         *     location for an active matrix attribute or an active attribute
-         *     array, both of which require multiple contiguous generic
-         *     attributes."
-         *
-         * Previous versions of the spec contain similar language but omit the
-         * bit about attribute arrays.
-         *
-         * Page 61 of the OpenGL 4.0 spec also says:
-         *
-         *     "It is possible for an application to bind more than one
-         *     attribute name to the same location. This is referred to as
-         *     aliasing. This will only work if only one of the aliased
-         *     attributes is active in the executable program, or if no path
-         *     through the shader consumes more than one attribute of a set
-         *     of attributes aliased to the same location. A link error can
-         *     occur if the linker determines that every path through the
-         *     shader consumes multiple aliased attributes, but
-         *     implementations are not required to generate an error in this
-         *     case."
-         *
-         * These two paragraphs are either somewhat contradictory, or I don't
-         * fully understand one or both of them.
-         */
-        /* FINISHME: The code as currently written does not support attribute
-         * FINISHME: location aliasing (see comment above).
-         */
-        const int attr = prog->Attributes->Parameters[i].StateIndexes[0];
-        const unsigned slots = count_attribute_slots(var->type);
-
-        /* Mask representing the contiguous slots that will be used by this
-         * attribute.
-         */
-        const unsigned use_mask = (1 << slots) - 1;
-
-        /* Generate a link error if the set of bits requested for this
-         * attribute overlaps any previously allocated bits.
-         */
-        if ((~(use_mask << attr) & used_locations) != used_locations) {
-           linker_error_printf(prog,
-                               "insufficient contiguous attribute locations "
-                               "available for vertex shader input `%s'",
-                               var->name);
-           return false;
-        }
-
-        var->location = VERT_ATTRIB_GENERIC0 + attr;
-        used_locations |= (use_mask << attr);
-      }
-   }
+   link_invalidate_variable_locations(sh, direction, generic_base);
 
    /* Temporary storage for the set of attributes that need locations assigned.
     */
@@ -1183,15 +1204,97 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
    foreach_list(node, sh->ir) {
       ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
-      if ((var == NULL) || (var->mode != ir_var_in))
+      if ((var == NULL) || (var->mode != (unsigned) direction))
         continue;
 
-      /* The location was explicitly assigned, nothing to do here.
+      if (var->explicit_location) {
+        if ((var->location >= (int)(max_index + generic_base))
+            || (var->location < 0)) {
+           linker_error(prog,
+                        "invalid explicit location %d specified for `%s'\n",
+                        (var->location < 0)
+                        ? var->location : var->location - generic_base,
+                        var->name);
+           return false;
+        }
+      } else if (target_index == MESA_SHADER_VERTEX) {
+        unsigned binding;
+
+        if (prog->AttributeBindings->get(binding, var->name)) {
+           assert(binding >= VERT_ATTRIB_GENERIC0);
+           var->location = binding;
+        }
+      } else if (target_index == MESA_SHADER_FRAGMENT) {
+        unsigned binding;
+
+        if (prog->FragDataBindings->get(binding, var->name)) {
+           assert(binding >= FRAG_RESULT_DATA0);
+           var->location = binding;
+        }
+      }
+
+      /* If the variable is not a built-in and has a location statically
+       * assigned in the shader (presumably via a layout qualifier), make sure
+       * that it doesn't collide with other assigned locations.  Otherwise,
+       * add it to the list of variables that need linker-assigned locations.
        */
-      if (var->location != -1)
+      const unsigned slots = count_attribute_slots(var->type);
+      if (var->location != -1) {
+        if (var->location >= generic_base) {
+           /* From page 61 of the OpenGL 4.0 spec:
+            *
+            *     "LinkProgram will fail if the attribute bindings assigned
+            *     by BindAttribLocation do not leave not enough space to
+            *     assign a location for an active matrix attribute or an
+            *     active attribute array, both of which require multiple
+            *     contiguous generic attributes."
+            *
+            * Previous versions of the spec contain similar language but omit
+            * the bit about attribute arrays.
+            *
+            * Page 61 of the OpenGL 4.0 spec also says:
+            *
+            *     "It is possible for an application to bind more than one
+            *     attribute name to the same location. This is referred to as
+            *     aliasing. This will only work if only one of the aliased
+            *     attributes is active in the executable program, or if no
+            *     path through the shader consumes more than one attribute of
+            *     a set of attributes aliased to the same location. A link
+            *     error can occur if the linker determines that every path
+            *     through the shader consumes multiple aliased attributes,
+            *     but implementations are not required to generate an error
+            *     in this case."
+            *
+            * These two paragraphs are either somewhat contradictory, or I
+            * don't fully understand one or both of them.
+            */
+           /* FINISHME: The code as currently written does not support
+            * FINISHME: attribute location aliasing (see comment above).
+            */
+           /* Mask representing the contiguous slots that will be used by
+            * this attribute.
+            */
+           const unsigned attr = var->location - generic_base;
+           const unsigned use_mask = (1 << slots) - 1;
+
+           /* Generate a link error if the set of bits requested for this
+            * attribute overlaps any previously allocated bits.
+            */
+           if ((~(use_mask << attr) & used_locations) != used_locations) {
+              linker_error(prog,
+                           "insufficient contiguous attribute locations "
+                           "available for vertex shader input `%s'",
+                           var->name);
+              return false;
+           }
+
+           used_locations |= (use_mask << attr);
+        }
+
         continue;
+      }
 
-      to_assign[num_attr].slots = count_attribute_slots(var->type);
+      to_assign[num_attr].slots = slots;
       to_assign[num_attr].var = var;
       num_attr++;
    }
@@ -1205,14 +1308,16 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
 
    qsort(to_assign, num_attr, sizeof(to_assign[0]), temp_attr::compare);
 
-   /* VERT_ATTRIB_GENERIC0 is a psdueo-alias for VERT_ATTRIB_POS.  It can only
-    * be explicitly assigned by via glBindAttribLocation.  Mark it as reserved
-    * to prevent it from being automatically allocated below.
-    */
-   find_deref_visitor find("gl_Vertex");
-   find.run(sh->ir);
-   if (find.variable_found())
-      used_locations |= (1 << 0);
+   if (target_index == MESA_SHADER_VERTEX) {
+      /* VERT_ATTRIB_GENERIC0 is a pseudo-alias for VERT_ATTRIB_POS.  It can
+       * only be explicitly assigned by via glBindAttribLocation.  Mark it as
+       * reserved to prevent it from being automatically allocated below.
+       */
+      find_deref_visitor find("gl_Vertex");
+      find.run(sh->ir);
+      if (find.variable_found())
+        used_locations |= (1 << 0);
+   }
 
    for (unsigned i = 0; i < num_attr; i++) {
       /* Mask representing the contiguous slots that will be used by this
@@ -1223,14 +1328,17 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
       int location = find_available_slots(used_locations, to_assign[i].slots);
 
       if (location < 0) {
-        linker_error_printf(prog,
-                            "insufficient contiguous attribute locations "
-                            "available for vertex shader input `%s'",
-                            to_assign[i].var->name);
+        const char *const string = (target_index == MESA_SHADER_VERTEX)
+           ? "vertex shader input" : "fragment shader output";
+
+        linker_error(prog,
+                     "insufficient contiguous attribute locations "
+                     "available for %s `%s'",
+                     string, to_assign[i].var->name);
         return false;
       }
 
-      to_assign[i].var->location = VERT_ATTRIB_GENERIC0 + location;
+      to_assign[i].var->location = generic_base + location;
       used_locations |= (use_mask << location);
    }
 
@@ -1239,19 +1347,20 @@ assign_attribute_locations(gl_shader_program *prog, unsigned max_attribute_index
 
 
 /**
- * Demote shader outputs that are not read to being just plain global variables
+ * Demote shader inputs and outputs that are not used in other stages
  */
 void
-demote_unread_shader_outputs(gl_shader *sh)
+demote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
 {
    foreach_list(node, sh->ir) {
       ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
-      if ((var == NULL) || (var->mode != ir_var_out))
+      if ((var == NULL) || (var->mode != int(mode)))
         continue;
 
-      /* An 'out' variable is only really a shader output if its value is read
-       * by the following stage.
+      /* A shader 'in' or 'out' variable is only really an input or output if
+       * its value is used by other shader stages.  This will cause the variable
+       * to have a location assigned.
        */
       if (var->location == -1) {
         var->mode = ir_var_auto;
@@ -1260,9 +1369,359 @@ demote_unread_shader_outputs(gl_shader *sh)
 }
 
 
+/**
+ * Data structure tracking information about a transform feedback declaration
+ * during linking.
+ */
+class tfeedback_decl
+{
+public:
+   bool init(struct gl_shader_program *prog, const void *mem_ctx,
+             const char *input);
+   static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y);
+   bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog,
+                        ir_variable *output_var);
+   bool store(struct gl_shader_program *prog,
+              struct gl_transform_feedback_info *info, unsigned buffer) const;
+
+
+   /**
+    * True if assign_location() has been called for this object.
+    */
+   bool is_assigned() const
+   {
+      return this->location != -1;
+   }
+
+   /**
+    * Determine whether this object refers to the variable var.
+    */
+   bool matches_var(ir_variable *var) const
+   {
+      return strcmp(var->name, this->var_name) == 0;
+   }
+
+   /**
+    * The total number of varying components taken up by this variable.  Only
+    * valid if is_assigned() is true.
+    */
+   unsigned num_components() const
+   {
+      return this->vector_elements * this->matrix_columns;
+   }
+
+private:
+   /**
+    * The name that was supplied to glTransformFeedbackVaryings.  Used for
+    * error reporting.
+    */
+   const char *orig_name;
+
+   /**
+    * The name of the variable, parsed from orig_name.
+    */
+   char *var_name;
+
+   /**
+    * True if the declaration in orig_name represents an array.
+    */
+   bool is_array;
+
+   /**
+    * If is_array is true, the array index that was specified in orig_name.
+    */
+   unsigned array_index;
+
+   /**
+    * The vertex shader output location that the linker assigned for this
+    * variable.  -1 if a location hasn't been assigned yet.
+    */
+   int location;
+
+   /**
+    * If location != -1, the number of vector elements in this variable, or 1
+    * if this variable is a scalar.
+    */
+   unsigned vector_elements;
+
+   /**
+    * If location != -1, the number of matrix columns in this variable, or 1
+    * if this variable is not a matrix.
+    */
+   unsigned matrix_columns;
+};
+
+
+/**
+ * Initialize this object based on a string that was passed to
+ * glTransformFeedbackVaryings.  If there is a parse error, the error is
+ * reported using linker_error(), and false is returned.
+ */
+bool
+tfeedback_decl::init(struct gl_shader_program *prog, const void *mem_ctx,
+                     const char *input)
+{
+   /* We don't have to be pedantic about what is a valid GLSL variable name,
+    * because any variable with an invalid name can't exist in the IR anyway.
+    */
+
+   this->location = -1;
+   this->orig_name = input;
+
+   const char *bracket = strrchr(input, '[');
+
+   if (bracket) {
+      this->var_name = ralloc_strndup(mem_ctx, input, bracket - input);
+      if (sscanf(bracket, "[%u]", &this->array_index) == 1) {
+         this->is_array = true;
+         return true;
+      }
+   } else {
+      this->var_name = ralloc_strdup(mem_ctx, input);
+      this->is_array = false;
+      return true;
+   }
+
+   linker_error(prog, "Cannot parse transform feedback varying %s", input);
+   return false;
+}
+
+
+/**
+ * Determine whether two tfeedback_decl objects refer to the same variable and
+ * array index (if applicable).
+ */
+bool
+tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
+{
+   if (strcmp(x.var_name, y.var_name) != 0)
+      return false;
+   if (x.is_array != y.is_array)
+      return false;
+   if (x.is_array && x.array_index != y.array_index)
+      return false;
+   return true;
+}
+
+
+/**
+ * Assign a location for this tfeedback_decl object based on the location
+ * assignment in output_var.
+ *
+ * If an error occurs, the error is reported through linker_error() and false
+ * is returned.
+ */
+bool
+tfeedback_decl::assign_location(struct gl_context *ctx,
+                                struct gl_shader_program *prog,
+                                ir_variable *output_var)
+{
+   if (output_var->type->is_array()) {
+      /* Array variable */
+      if (!this->is_array) {
+         linker_error(prog, "Transform feedback varying %s found, "
+                      "but it's not an array ([] not expected).",
+                      this->orig_name);
+         return false;
+      }
+      /* Check array bounds. */
+      if (this->array_index >=
+          (unsigned) output_var->type->array_size()) {
+         linker_error(prog, "Transform feedback varying %s has index "
+                      "%i, but the array size is %i.",
+                      this->orig_name, this->array_index,
+                      output_var->type->array_size());
+         return false;
+      }
+      const unsigned matrix_cols =
+         output_var->type->fields.array->matrix_columns;
+      this->location = output_var->location + this->array_index * matrix_cols;
+      this->vector_elements = output_var->type->fields.array->vector_elements;
+      this->matrix_columns = matrix_cols;
+   } else {
+      /* Regular variable (scalar, vector, or matrix) */
+      if (this->is_array) {
+         linker_error(prog, "Transform feedback varying %s found, "
+                      "but it's an array ([] expected).",
+                      this->orig_name);
+         return false;
+      }
+      this->location = output_var->location;
+      this->vector_elements = output_var->type->vector_elements;
+      this->matrix_columns = output_var->type->matrix_columns;
+   }
+   /* From GL_EXT_transform_feedback:
+    *   A program will fail to link if:
+    *
+    *   * the total number of components to capture in any varying
+    *     variable in <varyings> is greater than the constant
+    *     MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT and the
+    *     buffer mode is SEPARATE_ATTRIBS_EXT;
+    */
+   if (prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS &&
+       this->num_components() >
+       ctx->Const.MaxTransformFeedbackSeparateComponents) {
+      linker_error(prog, "Transform feedback varying %s exceeds "
+                   "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS.",
+                   this->orig_name);
+      return false;
+   }
+
+   return true;
+}
+
+
+/**
+ * Update gl_transform_feedback_info to reflect this tfeedback_decl.
+ *
+ * If an error occurs, the error is reported through linker_error() and false
+ * is returned.
+ */
+bool
+tfeedback_decl::store(struct gl_shader_program *prog,
+                      struct gl_transform_feedback_info *info,
+                      unsigned buffer) const
+{
+   if (!this->is_assigned()) {
+      /* From GL_EXT_transform_feedback:
+       *   A program will fail to link if:
+       *
+       *   * any variable name specified in the <varyings> array is not
+       *     declared as an output in the geometry shader (if present) or
+       *     the vertex shader (if no geometry shader is present);
+       */
+      linker_error(prog, "Transform feedback varying %s undeclared.",
+                   this->orig_name);
+      return false;
+   }
+   for (unsigned v = 0; v < this->matrix_columns; ++v) {
+      info->Outputs[info->NumOutputs].OutputRegister = this->location + v;
+      info->Outputs[info->NumOutputs].NumComponents = this->vector_elements;
+      info->Outputs[info->NumOutputs].OutputBuffer = buffer;
+      ++info->NumOutputs;
+   }
+   return true;
+}
+
+
+/**
+ * Parse all the transform feedback declarations that were passed to
+ * glTransformFeedbackVaryings() and store them in tfeedback_decl objects.
+ *
+ * If an error occurs, the error is reported through linker_error() and false
+ * is returned.
+ */
+static bool
+parse_tfeedback_decls(struct gl_shader_program *prog, const void *mem_ctx,
+                      unsigned num_names, char **varying_names,
+                      tfeedback_decl *decls)
+{
+   for (unsigned i = 0; i < num_names; ++i) {
+      if (!decls[i].init(prog, mem_ctx, varying_names[i]))
+         return false;
+      /* From GL_EXT_transform_feedback:
+       *   A program will fail to link if:
+       *
+       *   * any two entries in the <varyings> array specify the same varying
+       *     variable;
+       *
+       * We interpret this to mean "any two entries in the <varyings> array
+       * specify the same varying variable and array index", since transform
+       * feedback of arrays would be useless otherwise.
+       */
+      for (unsigned j = 0; j < i; ++j) {
+         if (tfeedback_decl::is_same(decls[i], decls[j])) {
+            linker_error(prog, "Transform feedback varying %s specified "
+                         "more than once.", varying_names[i]);
+            return false;
+         }
+      }
+   }
+   return true;
+}
+
+
+/**
+ * Assign a location for a variable that is produced in one pipeline stage
+ * (the "producer") and consumed in the next stage (the "consumer").
+ *
+ * \param input_var is the input variable declaration in the consumer.
+ *
+ * \param output_var is the output variable declaration in the producer.
+ *
+ * \param input_index is the counter that keeps track of assigned input
+ *        locations in the consumer.
+ *
+ * \param output_index is the counter that keeps track of assigned output
+ *        locations in the producer.
+ *
+ * It is permissible for \c input_var to be NULL (this happens if a variable
+ * is output by the producer and consumed by transform feedback, but not
+ * consumed by the consumer).
+ *
+ * If the variable has already been assigned a location, this function has no
+ * effect.
+ */
 void
-assign_varying_locations(struct gl_shader_program *prog,
-                        gl_shader *producer, gl_shader *consumer)
+assign_varying_location(ir_variable *input_var, ir_variable *output_var,
+                        unsigned *input_index, unsigned *output_index)
+{
+   if (output_var->location != -1) {
+      /* Location already assigned. */
+      return;
+   }
+
+   if (input_var) {
+      assert(input_var->location == -1);
+      input_var->location = *input_index;
+   }
+
+   output_var->location = *output_index;
+
+   /* FINISHME: Support for "varying" records in GLSL 1.50. */
+   assert(!output_var->type->is_record());
+
+   if (output_var->type->is_array()) {
+      const unsigned slots = output_var->type->length
+         * output_var->type->fields.array->matrix_columns;
+
+      *output_index += slots;
+      *input_index += slots;
+   } else {
+      const unsigned slots = output_var->type->matrix_columns;
+
+      *output_index += slots;
+      *input_index += slots;
+   }
+}
+
+
+/**
+ * Assign locations for all variables that are produced in one pipeline stage
+ * (the "producer") and consumed in the next stage (the "consumer").
+ *
+ * Variables produced by the producer may also be consumed by transform
+ * feedback.
+ *
+ * \param num_tfeedback_decls is the number of declarations indicating
+ *        variables that may be consumed by transform feedback.
+ *
+ * \param tfeedback_decls is a pointer to an array of tfeedback_decl objects
+ *        representing the result of parsing the strings passed to
+ *        glTransformFeedbackVaryings().  assign_location() will be called for
+ *        each of these objects that matches one of the outputs of the
+ *        producer.
+ *
+ * When num_tfeedback_decls is nonzero, it is permissible for the consumer to
+ * be NULL.  In this case, varying locations are assigned solely based on the
+ * requirements of transform feedback.
+ */
+bool
+assign_varying_locations(struct gl_context *ctx,
+                        struct gl_shader_program *prog,
+                        gl_shader *producer, gl_shader *consumer,
+                         unsigned num_tfeedback_decls,
+                         tfeedback_decl *tfeedback_decls)
 {
    /* FINISHME: Set dynamically when geometry shader support is added. */
    unsigned output_index = VERT_RESULT_VAR0;
@@ -1279,92 +1738,252 @@ assign_varying_locations(struct gl_shader_program *prog,
     *    not being inputs.  This lets the optimizer eliminate them.
     */
 
-   invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0);
-   invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0);
+   link_invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0);
+   if (consumer)
+      link_invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0);
 
    foreach_list(node, producer->ir) {
       ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
 
-      if ((output_var == NULL) || (output_var->mode != ir_var_out)
-         || (output_var->location != -1))
+      if ((output_var == NULL) || (output_var->mode != ir_var_out))
         continue;
 
-      ir_variable *const input_var =
-        consumer->symbols->get_variable(output_var->name);
+      ir_variable *input_var =
+        consumer ? consumer->symbols->get_variable(output_var->name) : NULL;
 
-      if ((input_var == NULL) || (input_var->mode != ir_var_in))
-        continue;
+      if (input_var && input_var->mode != ir_var_in)
+         input_var = NULL;
 
-      assert(input_var->location == -1);
+      if (input_var) {
+         assign_varying_location(input_var, output_var, &input_index,
+                                 &output_index);
+      }
 
-      output_var->location = output_index;
-      input_var->location = input_index;
+      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+         if (!tfeedback_decls[i].is_assigned() &&
+             tfeedback_decls[i].matches_var(output_var)) {
+            if (output_var->location == -1) {
+               assign_varying_location(input_var, output_var, &input_index,
+                                       &output_index);
+            }
+            if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
+               return false;
+         }
+      }
+   }
+
+   unsigned varying_vectors = 0;
+
+   if (consumer) {
+      foreach_list(node, consumer->ir) {
+         ir_variable *const var = ((ir_instruction *) node)->as_variable();
+
+         if ((var == NULL) || (var->mode != ir_var_in))
+            continue;
+
+         if (var->location == -1) {
+            if (prog->Version <= 120) {
+               /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
+                *
+                *     Only those varying variables used (i.e. read) in
+                *     the fragment shader executable must be written to
+                *     by the vertex shader executable; declaring
+                *     superfluous varying variables in a vertex shader is
+                *     permissible.
+                *
+                * We interpret this text as meaning that the VS must
+                * write the variable for the FS to read it.  See
+                * "glsl1-varying read but not written" in piglit.
+                */
+
+               linker_error(prog, "fragment shader varying %s not written "
+                            "by vertex shader\n.", var->name);
+            }
+
+            /* An 'in' variable is only really a shader input if its
+             * value is written by the previous stage.
+             */
+            var->mode = ir_var_auto;
+         } else {
+            /* The packing rules are used for vertex shader inputs are also
+             * used for fragment shader inputs.
+             */
+            varying_vectors += count_attribute_slots(var->type);
+         }
+      }
+   }
 
-      /* FINISHME: Support for "varying" records in GLSL 1.50. */
-      assert(!output_var->type->is_record());
+   if (ctx->API == API_OPENGLES2 || prog->Version == 100) {
+      if (varying_vectors > ctx->Const.MaxVarying) {
+        linker_error(prog, "shader uses too many varying vectors "
+                     "(%u > %u)\n",
+                     varying_vectors, ctx->Const.MaxVarying);
+        return false;
+      }
+   } else {
+      const unsigned float_components = varying_vectors * 4;
+      if (float_components > ctx->Const.MaxVarying * 4) {
+        linker_error(prog, "shader uses too many varying components "
+                     "(%u > %u)\n",
+                     float_components, ctx->Const.MaxVarying * 4);
+        return false;
+      }
+   }
 
-      if (output_var->type->is_array()) {
-        const unsigned slots = output_var->type->length
-           * output_var->type->fields.array->matrix_columns;
+   return true;
+}
 
-        output_index += slots;
-        input_index += slots;
-      } else {
-        const unsigned slots = output_var->type->matrix_columns;
 
-        output_index += slots;
-        input_index += slots;
-      }
+/**
+ * Store transform feedback location assignments into
+ * prog->LinkedTransformFeedback based on the data stored in tfeedback_decls.
+ *
+ * If an error occurs, the error is reported through linker_error() and false
+ * is returned.
+ */
+static bool
+store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
+                     unsigned num_tfeedback_decls,
+                     tfeedback_decl *tfeedback_decls)
+{
+   unsigned total_tfeedback_components = 0;
+   prog->LinkedTransformFeedback.NumOutputs = 0;
+   for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+      unsigned buffer =
+         prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS ? i : 0;
+      if (!tfeedback_decls[i].store(prog, &prog->LinkedTransformFeedback,
+                                    buffer))
+         return false;
+      total_tfeedback_components += tfeedback_decls[i].num_components();
    }
 
-   demote_unread_shader_outputs(producer);
+   /* From GL_EXT_transform_feedback:
+    *   A program will fail to link if:
+    *
+    *     * the total number of components to capture is greater than
+    *       the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT
+    *       and the buffer mode is INTERLEAVED_ATTRIBS_EXT.
+    */
+   if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS &&
+       total_tfeedback_components >
+       ctx->Const.MaxTransformFeedbackInterleavedComponents) {
+      linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
+                   "limit has been exceeded.");
+      return false;
+   }
 
-   foreach_list(node, consumer->ir) {
-      ir_variable *const var = ((ir_instruction *) node)->as_variable();
+   return true;
+}
 
-      if ((var == NULL) || (var->mode != ir_var_in))
-        continue;
+/**
+ * Store the gl_FragDepth layout in the gl_shader_program struct.
+ */
+static void
+store_fragdepth_layout(struct gl_shader_program *prog)
+{
+   if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
+      return;
+   }
 
-      if (var->location == -1) {
-        if (prog->Version <= 120) {
-           /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
-            *
-            *     Only those varying variables used (i.e. read) in
-            *     the fragment shader executable must be written to
-            *     by the vertex shader executable; declaring
-            *     superfluous varying variables in a vertex shader is
-            *     permissible.
-            *
-            * We interpret this text as meaning that the VS must
-            * write the variable for the FS to read it.  See
-            * "glsl1-varying read but not written" in piglit.
-            */
+   struct exec_list *ir = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
 
-           linker_error_printf(prog, "fragment shader varying %s not written "
-                               "by vertex shader\n.", var->name);
-           prog->LinkStatus = false;
-        }
+   /* We don't look up the gl_FragDepth symbol directly because if
+    * gl_FragDepth is not used in the shader, it's removed from the IR.
+    * However, the symbol won't be removed from the symbol table.
+    *
+    * We're only interested in the cases where the variable is NOT removed
+    * from the IR.
+    */
+   foreach_list(node, ir) {
+      ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
-        /* An 'in' variable is only really a shader input if its
-         * value is written by the previous stage.
-         */
-        var->mode = ir_var_auto;
+      if (var == NULL || var->mode != ir_var_out) {
+         continue;
+      }
+
+      if (strcmp(var->name, "gl_FragDepth") == 0) {
+         switch (var->depth_layout) {
+         case ir_depth_layout_none:
+            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE;
+            return;
+         case ir_depth_layout_any:
+            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY;
+            return;
+         case ir_depth_layout_greater:
+            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER;
+            return;
+         case ir_depth_layout_less:
+            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS;
+            return;
+         case ir_depth_layout_unchanged:
+            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED;
+            return;
+         default:
+            assert(0);
+            return;
+         }
       }
    }
 }
 
+/**
+ * Validate the resources used by a program versus the implementation limits
+ */
+static bool
+check_resources(struct gl_context *ctx, struct gl_shader_program *prog)
+{
+   static const char *const shader_names[MESA_SHADER_TYPES] = {
+      "vertex", "fragment", "geometry"
+   };
+
+   const unsigned max_samplers[MESA_SHADER_TYPES] = {
+      ctx->Const.MaxVertexTextureImageUnits,
+      ctx->Const.MaxTextureImageUnits,
+      ctx->Const.MaxGeometryTextureImageUnits
+   };
+
+   const unsigned max_uniform_components[MESA_SHADER_TYPES] = {
+      ctx->Const.VertexProgram.MaxUniformComponents,
+      ctx->Const.FragmentProgram.MaxUniformComponents,
+      0          /* FINISHME: Geometry shaders. */
+   };
+
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      struct gl_shader *sh = prog->_LinkedShaders[i];
+
+      if (sh == NULL)
+        continue;
+
+      if (sh->num_samplers > max_samplers[i]) {
+        linker_error(prog, "Too many %s shader texture samplers",
+                     shader_names[i]);
+      }
+
+      if (sh->num_uniform_components > max_uniform_components[i]) {
+         linker_error(prog, "Too many %s shader uniform components",
+                     shader_names[i]);
+      }
+   }
+
+   return prog->LinkStatus;
+}
 
 void
-link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
+link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
 {
+   tfeedback_decl *tfeedback_decls = NULL;
+   unsigned num_tfeedback_decls = prog->TransformFeedback.NumVarying;
+
+   void *mem_ctx = ralloc_context(NULL); // temporary linker context
+
    prog->LinkStatus = false;
    prog->Validated = false;
    prog->_Used = false;
 
    if (prog->InfoLog != NULL)
-      talloc_free(prog->InfoLog);
+      ralloc_free(prog->InfoLog);
 
-   prog->InfoLog = talloc_strdup(NULL, "");
+   prog->InfoLog = ralloc_strdup(NULL, "");
 
    /* Separate the shaders into groups based on their type.
     */
@@ -1407,46 +2026,50 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
    assert(max_version <= 130);
    if ((max_version >= 130 || min_version == 100)
        && min_version != max_version) {
-      linker_error_printf(prog, "all shaders must use same shading "
-                         "language version\n");
+      linker_error(prog, "all shaders must use same shading "
+                  "language version\n");
       goto done;
    }
 
    prog->Version = max_version;
 
-   for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) {
-      ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+   for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] != NULL)
+        ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+
+      prog->_LinkedShaders[i] = NULL;
    }
 
    /* Link all shaders for a particular stage and validate the result.
     */
-   prog->_NumLinkedShaders = 0;
    if (num_vert_shaders > 0) {
       gl_shader *const sh =
-        link_intrastage_shaders(ctx, prog, vert_shader_list, num_vert_shaders);
+        link_intrastage_shaders(mem_ctx, ctx, prog, vert_shader_list,
+                                num_vert_shaders);
 
       if (sh == NULL)
         goto done;
 
       if (!validate_vertex_shader_executable(prog, sh))
-         goto done;
+        goto done;
 
-      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
-      prog->_NumLinkedShaders++;
+      _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_VERTEX],
+                            sh);
    }
 
    if (num_frag_shaders > 0) {
       gl_shader *const sh =
-        link_intrastage_shaders(ctx, prog, frag_shader_list, num_frag_shaders);
+        link_intrastage_shaders(mem_ctx, ctx, prog, frag_shader_list,
+                                num_frag_shaders);
 
       if (sh == NULL)
         goto done;
 
       if (!validate_fragment_shader_executable(prog, sh))
-         goto done;
+        goto done;
 
-      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
-      prog->_NumLinkedShaders++;
+      _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
+                            sh);
    }
 
    /* Here begins the inter-stage linking phase.  Some initial validation is
@@ -1454,14 +2077,26 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
     * varyings.
     */
    if (cross_validate_uniforms(prog)) {
-      /* Validate the inputs of each stage with the output of the preceeding
+      unsigned prev;
+
+      for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
+        if (prog->_LinkedShaders[prev] != NULL)
+           break;
+      }
+
+      /* Validate the inputs of each stage with the output of the preceding
        * stage.
        */
-      for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
+      for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
+        if (prog->_LinkedShaders[i] == NULL)
+           continue;
+
         if (!cross_validate_outputs_to_inputs(prog,
-                                              prog->_LinkedShaders[i - 1],
+                                              prog->_LinkedShaders[prev],
                                               prog->_LinkedShaders[i]))
            goto done;
+
+        prev = i;
       }
 
       prog->LinkStatus = true;
@@ -1471,37 +2106,166 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
     * uniforms, and varyings.  Later optimization could possibly make
     * some of that unused.
     */
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
-      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, 32))
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+        continue;
+
+      detect_recursion_linked(prog, prog->_LinkedShaders[i]->ir);
+      if (!prog->LinkStatus)
+        goto done;
+
+      if (ctx->ShaderCompilerOptions[i].LowerClipDistance)
+         lower_clip_distance(prog->_LinkedShaders[i]->ir);
+
+      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, 32))
         ;
    }
 
-   update_array_sizes(prog);
+   /* FINISHME: The value of the max_attribute_index parameter is
+    * FINISHME: implementation dependent based on the value of
+    * FINISHME: GL_MAX_VERTEX_ATTRIBS.  GL_MAX_VERTEX_ATTRIBS must be
+    * FINISHME: at least 16, so hardcode 16 for now.
+    */
+   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_VERTEX, 16)) {
+      goto done;
+   }
 
-   assign_uniform_locations(prog);
+   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, ctx->Const.MaxDrawBuffers)) {
+      goto done;
+   }
 
-   if (prog->_NumLinkedShaders && prog->_LinkedShaders[0]->Type == GL_VERTEX_SHADER) {
-      /* FINISHME: The value of the max_attribute_index parameter is
-       * FINISHME: implementation dependent based on the value of
-       * FINISHME: GL_MAX_VERTEX_ATTRIBS.  GL_MAX_VERTEX_ATTRIBS must be
-       * FINISHME: at least 16, so hardcode 16 for now.
+   unsigned prev;
+   for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
+      if (prog->_LinkedShaders[prev] != NULL)
+        break;
+   }
+
+   if (num_tfeedback_decls != 0) {
+      /* From GL_EXT_transform_feedback:
+       *   A program will fail to link if:
+       *
+       *   * the <count> specified by TransformFeedbackVaryingsEXT is
+       *     non-zero, but the program object has no vertex or geometry
+       *     shader;
        */
-      if (!assign_attribute_locations(prog, 16)) {
-        prog->LinkStatus = false;
-        goto done;
+      if (prev >= MESA_SHADER_FRAGMENT) {
+         linker_error(prog, "Transform feedback varyings specified, but "
+                      "no vertex or geometry shader is present.");
+         goto done;
       }
 
-      if (prog->_NumLinkedShaders == 1)
-        demote_unread_shader_outputs(prog->_LinkedShaders[0]);
+      tfeedback_decls = ralloc_array(mem_ctx, tfeedback_decl,
+                                     prog->TransformFeedback.NumVarying);
+      if (!parse_tfeedback_decls(prog, mem_ctx, num_tfeedback_decls,
+                                 prog->TransformFeedback.VaryingNames,
+                                 tfeedback_decls))
+         goto done;
    }
 
-   for (unsigned i = 1; i < prog->_NumLinkedShaders; i++)
-      assign_varying_locations(prog,
-                              prog->_LinkedShaders[i - 1],
-                              prog->_LinkedShaders[i]);
+   for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+        continue;
+
+      if (!assign_varying_locations(
+             ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i],
+             i == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
+             tfeedback_decls))
+        goto done;
+
+      prev = i;
+   }
+
+   if (prev != MESA_SHADER_FRAGMENT && num_tfeedback_decls != 0) {
+      /* There was no fragment shader, but we still have to assign varying
+       * locations for use by transform feedback.
+       */
+      if (!assign_varying_locations(
+             ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls,
+             tfeedback_decls))
+         goto done;
+   }
+
+   if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls))
+      goto done;
+
+   if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
+      demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX],
+                                      ir_var_out);
+
+      /* Eliminate code that is now dead due to unused vertex outputs being
+       * demoted.
+       */
+      while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir, false))
+        ;
+   }
+
+   if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
+      gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_GEOMETRY];
+
+      demote_shader_inputs_and_outputs(sh, ir_var_in);
+      demote_shader_inputs_and_outputs(sh, ir_var_inout);
+      demote_shader_inputs_and_outputs(sh, ir_var_out);
+
+      /* Eliminate code that is now dead due to unused geometry outputs being
+       * demoted.
+       */
+      while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir, false))
+        ;
+   }
+
+   if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) {
+      gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+
+      demote_shader_inputs_and_outputs(sh, ir_var_in);
+
+      /* Eliminate code that is now dead due to unused fragment inputs being
+       * demoted.  This shouldn't actually do anything other than remove
+       * declarations of the (now unused) global variables.
+       */
+      while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir, false))
+        ;
+   }
+
+   update_array_sizes(prog);
+   link_assign_uniform_locations(prog);
+   store_fragdepth_layout(prog);
+
+   if (!check_resources(ctx, prog))
+      goto done;
+
+   /* OpenGL ES requires that a vertex shader and a fragment shader both be
+    * present in a linked program.  By checking for use of shading language
+    * version 1.00, we also catch the GL_ARB_ES2_compatibility case.
+    */
+   if (!prog->InternalSeparateShader &&
+       (ctx->API == API_OPENGLES2 || prog->Version == 100)) {
+      if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
+        linker_error(prog, "program lacks a vertex shader\n");
+      } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
+        linker_error(prog, "program lacks a fragment shader\n");
+      }
+   }
 
    /* FINISHME: Assign fragment shader output locations. */
 
 done:
    free(vert_shader_list);
+
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+        continue;
+
+      /* Retain any live IR, but trash the rest. */
+      reparent_ir(prog->_LinkedShaders[i]->ir, prog->_LinkedShaders[i]->ir);
+
+      /* The symbol table in the linked shaders may contain references to
+       * variables that were removed (e.g., unused uniforms).  Since it may
+       * contain junk, there is no possible valid use.  Delete it and set the
+       * pointer to NULL.
+       */
+      delete prog->_LinkedShaders[i]->symbols;
+      prog->_LinkedShaders[i]->symbols = NULL;
+   }
+
+   ralloc_free(mem_ctx);
 }