From 0b9b391c5a7acb31e5d8061169649043a38d6d0e Mon Sep 17 00:00:00 2001
From: marha <marha@users.sourceforge.net>
Date: Mon, 28 Mar 2011 10:22:02 +0000
Subject: xserver xkeyboard-config mesa git update 28 Mar 2011

---
 mesalib/src/glsl/ast_to_hir.cpp       |   13 +-
 mesalib/src/glsl/glsl_parser_extras.h |    4 +-
 mesalib/src/glsl/ir_print_visitor.cpp |  989 ++++++++++++++--------------
 mesalib/src/glsl/ir_print_visitor.h   |   29 +-
 mesalib/src/glsl/ir_validate.cpp      | 1139 +++++++++++++++++----------------
 mesalib/src/glsl/ir_variable.cpp      |  215 ++++---
 6 files changed, 1233 insertions(+), 1156 deletions(-)

(limited to 'mesalib/src/glsl')

diff --git a/mesalib/src/glsl/ast_to_hir.cpp b/mesalib/src/glsl/ast_to_hir.cpp
index cdb16fd49..9538aa62b 100644
--- a/mesalib/src/glsl/ast_to_hir.cpp
+++ b/mesalib/src/glsl/ast_to_hir.cpp
@@ -1577,7 +1577,7 @@ ast_expression::hir(exec_list *instructions,
 	     */
 	    ir_variable *v = array->whole_variable_referenced();
 	    if (v != NULL)
-	       v->max_array_access = array->type->array_size();
+	       v->max_array_access = array->type->array_size() - 1;
 	 }
       }
 
@@ -2676,17 +2676,24 @@ ast_declarator_list::hir(exec_list *instructions,
        *    preceded by one of these precision qualifiers [...] Literal
        *    constants do not have precision qualifiers. Neither do Boolean
        *    variables.
+       *
+       * In GLSL ES, sampler types are also allowed.
+       *
+       * From page 87 of the GLSL ES spec:
+       *    "RESOLUTION: Allow sampler types to take a precision qualifier."
        */
       if (this->type->specifier->precision != ast_precision_none
           && !var->type->is_float()
           && !var->type->is_integer()
+          && !(var->type->is_sampler() && state->es_shader)
           && !(var->type->is_array()
                && (var->type->fields.array->is_float()
                    || var->type->fields.array->is_integer()))) {
 
          _mesa_glsl_error(&loc, state,
-                          "precision qualifiers apply only to floating point "
-                          "and integer types");
+                          "precision qualifiers apply only to floating point"
+                          "%s types", state->es_shader ? ", integer, and sampler"
+						       : "and integer");
       }
 
       /* Process the initializer and add its instructions to a temporary
diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h
index b5c016fb3..6df0e160a 100644
--- a/mesalib/src/glsl/glsl_parser_extras.h
+++ b/mesalib/src/glsl/glsl_parser_extras.h
@@ -268,8 +268,8 @@ extern "C" {
 extern int preprocess(void *ctx, const char **shader, char **info_log,
                       const struct gl_extensions *extensions, int api);
 
-extern void _mesa_destroy_shader_compiler();
-extern void _mesa_destroy_shader_compiler_caches();
+extern void _mesa_destroy_shader_compiler(void);
+extern void _mesa_destroy_shader_compiler_caches(void);
 
 #ifdef __cplusplus
 }
diff --git a/mesalib/src/glsl/ir_print_visitor.cpp b/mesalib/src/glsl/ir_print_visitor.cpp
index 3c5c4fd20..02f3d8149 100644
--- a/mesalib/src/glsl/ir_print_visitor.cpp
+++ b/mesalib/src/glsl/ir_print_visitor.cpp
@@ -1,474 +1,515 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-#include "ir_print_visitor.h"
-#include "glsl_types.h"
-#include "glsl_parser_extras.h"
-
-static void print_type(const glsl_type *t);
-
-void
-ir_instruction::print(void) const
-{
-   ir_instruction *deconsted = const_cast<ir_instruction *>(this);
-
-   ir_print_visitor v;
-   deconsted->accept(&v);
-}
-
-void
-_mesa_print_ir(exec_list *instructions,
-	       struct _mesa_glsl_parse_state *state)
-{
-   if (state) {
-      for (unsigned i = 0; i < state->num_user_structures; i++) {
-	 const glsl_type *const s = state->user_structures[i];
-
-	 printf("(structure (%s) (%s@%p) (%u) (\n",
-		s->name, s->name, (void *) s, s->length);
-
-	 for (unsigned j = 0; j < s->length; j++) {
-	    printf("\t((");
-	    print_type(s->fields.structure[j].type);
-	    printf(")(%s))\n", s->fields.structure[j].name);
-	 }
-
-	 printf(")\n");
-      }
-   }
-
-   printf("(\n");
-   foreach_iter(exec_list_iterator, iter, *instructions) {
-      ir_instruction *ir = (ir_instruction *)iter.get();
-      ir->print();
-      if (ir->ir_type != ir_type_function)
-	 printf("\n");
-   }
-   printf("\n)");
-}
-
-
-void ir_print_visitor::indent(void)
-{
-   for (int i = 0; i < indentation; i++)
-      printf("  ");
-}
-
-static void
-print_type(const glsl_type *t)
-{
-   if (t->base_type == GLSL_TYPE_ARRAY) {
-      printf("(array ");
-      print_type(t->fields.array);
-      printf(" %u)", t->length);
-   } else if ((t->base_type == GLSL_TYPE_STRUCT)
-	      && (strncmp("gl_", t->name, 3) != 0)) {
-      printf("%s@%p", t->name, (void *) t);
-   } else {
-      printf("%s", t->name);
-   }
-}
-
-
-void ir_print_visitor::visit(ir_variable *ir)
-{
-   printf("(declare ");
-
-   const char *const cent = (ir->centroid) ? "centroid " : "";
-   const char *const inv = (ir->invariant) ? "invariant " : "";
-   const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
-			        "const_in ", "sys ", "temporary " };
-   const char *const interp[] = { "", "flat", "noperspective" };
-
-   printf("(%s%s%s%s) ",
-	  cent, inv, mode[ir->mode], interp[ir->interpolation]);
-
-   print_type(ir->type);
-   printf(" %s@%p)", ir->name, (void *) ir);
-}
-
-
-void ir_print_visitor::visit(ir_function_signature *ir)
-{
-   printf("(signature ");
-   indentation++;
-
-   print_type(ir->return_type);
-   printf("\n");
-   indent();
-
-   printf("(parameters\n");
-   indentation++;
-
-   foreach_iter(exec_list_iterator, iter, ir->parameters) {
-      ir_variable *const inst = (ir_variable *) iter.get();
-
-      indent();
-      inst->accept(this);
-      printf("\n");
-   }
-   indentation--;
-
-   indent();
-   printf(")\n");
-
-   indent();
-
-   printf("(\n");
-   indentation++;
-
-   foreach_iter(exec_list_iterator, iter, ir->body) {
-      ir_instruction *const inst = (ir_instruction *) iter.get();
-
-      indent();
-      inst->accept(this);
-      printf("\n");
-   }
-   indentation--;
-   indent();
-   printf("))\n");
-   indentation--;
-}
-
-
-void ir_print_visitor::visit(ir_function *ir)
-{
-   printf("(function %s\n", ir->name);
-   indentation++;
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_function_signature *const sig = (ir_function_signature *) iter.get();
-      indent();
-      sig->accept(this);
-      printf("\n");
-   }
-   indentation--;
-   indent();
-   printf(")\n\n");
-}
-
-
-void ir_print_visitor::visit(ir_expression *ir)
-{
-   printf("(expression ");
-
-   print_type(ir->type);
-
-   printf(" %s ", ir->operator_string());
-
-   for (unsigned i = 0; i < ir->get_num_operands(); i++) {
-      ir->operands[i]->accept(this);
-   }
-
-   printf(") ");
-}
-
-
-void ir_print_visitor::visit(ir_texture *ir)
-{
-   printf("(%s ", ir->opcode_string());
-
-   print_type(ir->type);
-   printf(" ");
-
-   ir->sampler->accept(this);
-   printf(" ");
-
-   ir->coordinate->accept(this);
-
-   printf(" ");
-
-   if (ir->offset != NULL) {
-      ir->offset->accept(this);
-   } else {
-      printf("0");
-   }
-
-   printf(" ");
-
-   if (ir->op != ir_txf) {
-      if (ir->projector)
-	 ir->projector->accept(this);
-      else
-	 printf("1");
-
-      if (ir->shadow_comparitor) {
-	 printf(" ");
-	 ir->shadow_comparitor->accept(this);
-      } else {
-	 printf(" ()");
-      }
-   }
-
-   printf(" ");
-   switch (ir->op)
-   {
-   case ir_tex:
-      break;
-   case ir_txb:
-      ir->lod_info.bias->accept(this);
-      break;
-   case ir_txl:
-   case ir_txf:
-      ir->lod_info.lod->accept(this);
-      break;
-   case ir_txd:
-      printf("(");
-      ir->lod_info.grad.dPdx->accept(this);
-      printf(" ");
-      ir->lod_info.grad.dPdy->accept(this);
-      printf(")");
-      break;
-   };
-   printf(")");
-}
-
-
-void ir_print_visitor::visit(ir_swizzle *ir)
-{
-   const unsigned swiz[4] = {
-      ir->mask.x,
-      ir->mask.y,
-      ir->mask.z,
-      ir->mask.w,
-   };
-
-   printf("(swiz ");
-   for (unsigned i = 0; i < ir->mask.num_components; i++) {
-      printf("%c", "xyzw"[swiz[i]]);
-   }
-   printf(" ");
-   ir->val->accept(this);
-   printf(")");
-}
-
-
-void ir_print_visitor::visit(ir_dereference_variable *ir)
-{
-   ir_variable *var = ir->variable_referenced();
-   printf("(var_ref %s@%p) ", var->name, (void *) var);
-}
-
-
-void ir_print_visitor::visit(ir_dereference_array *ir)
-{
-   printf("(array_ref ");
-   ir->array->accept(this);
-   ir->array_index->accept(this);
-   printf(") ");
-}
-
-
-void ir_print_visitor::visit(ir_dereference_record *ir)
-{
-   printf("(record_ref ");
-   ir->record->accept(this);
-   printf(" %s) ", ir->field);
-}
-
-
-void ir_print_visitor::visit(ir_assignment *ir)
-{
-   printf("(assign ");
-
-   if (ir->condition)
-      ir->condition->accept(this);
-
-   char mask[5];
-   unsigned j = 0;
-
-   for (unsigned i = 0; i < 4; i++) {
-      if ((ir->write_mask & (1 << i)) != 0) {
-	 mask[j] = "xyzw"[i];
-	 j++;
-      }
-   }
-   mask[j] = '\0';
-
-   printf(" (%s) ", mask);
-
-   ir->lhs->accept(this);
-
-   printf(" ");
-
-   ir->rhs->accept(this);
-   printf(") ");
-}
-
-
-void ir_print_visitor::visit(ir_constant *ir)
-{
-   const glsl_type *const base_type = ir->type->get_base_type();
-
-   printf("(constant ");
-   print_type(ir->type);
-   printf(" (");
-
-   if (ir->type->is_array()) {
-      for (unsigned i = 0; i < ir->type->length; i++)
-	 ir->get_array_element(i)->accept(this);
-   } else if (ir->type->is_record()) {
-      ir_constant *value = (ir_constant *) ir->components.get_head();
-      for (unsigned i = 0; i < ir->type->length; i++) {
-	 printf("(%s ", ir->type->fields.structure->name);
-	 value->accept(this);
-	 printf(")");
-
-	 value = (ir_constant *) value->next;
-      }
-   } else {
-      for (unsigned i = 0; i < ir->type->components(); i++) {
-	 if (i != 0)
-	    printf(" ");
-	 switch (base_type->base_type) {
-	 case GLSL_TYPE_UINT:  printf("%u", ir->value.u[i]); break;
-	 case GLSL_TYPE_INT:   printf("%d", ir->value.i[i]); break;
-	 case GLSL_TYPE_FLOAT: printf("%f", ir->value.f[i]); break;
-	 case GLSL_TYPE_BOOL:  printf("%d", ir->value.b[i]); break;
-	 default: assert(0);
-	 }
-      }
-   }
-   printf(")) ");
-}
-
-
-void
-ir_print_visitor::visit(ir_call *ir)
-{
-   printf("(call %s (", ir->callee_name());
-   foreach_iter(exec_list_iterator, iter, *ir) {
-      ir_instruction *const inst = (ir_instruction *) iter.get();
-
-      inst->accept(this);
-   }
-   printf("))\n");
-}
-
-
-void
-ir_print_visitor::visit(ir_return *ir)
-{
-   printf("(return");
-
-   ir_rvalue *const value = ir->get_value();
-   if (value) {
-      printf(" ");
-      value->accept(this);
-   }
-
-   printf(")");
-}
-
-
-void
-ir_print_visitor::visit(ir_discard *ir)
-{
-   printf("(discard ");
-
-   if (ir->condition != NULL) {
-      printf(" ");
-      ir->condition->accept(this);
-   }
-
-   printf(")");
-}
-
-
-void
-ir_print_visitor::visit(ir_if *ir)
-{
-   printf("(if ");
-   ir->condition->accept(this);
-
-   printf("(\n");
-   indentation++;
-
-   foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
-      ir_instruction *const inst = (ir_instruction *) iter.get();
-
-      indent();
-      inst->accept(this);
-      printf("\n");
-   }
-
-   indentation--;
-   indent();
-   printf(")\n");
-
-   indent();
-   if (!ir->else_instructions.is_empty()) {
-      printf("(\n");
-      indentation++;
-
-      foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
-	 ir_instruction *const inst = (ir_instruction *) iter.get();
-
-	 indent();
-	 inst->accept(this);
-	 printf("\n");
-      }
-      indentation--;
-      indent();
-      printf("))\n");
-   } else {
-      printf("())\n");
-   }
-}
-
-
-void
-ir_print_visitor::visit(ir_loop *ir)
-{
-   printf("(loop (");
-   if (ir->counter != NULL)
-      ir->counter->accept(this);
-   printf(") (");
-   if (ir->from != NULL)
-      ir->from->accept(this);
-   printf(") (");
-   if (ir->to != NULL)
-      ir->to->accept(this);
-   printf(") (");
-   if (ir->increment != NULL)
-      ir->increment->accept(this);
-   printf(") (\n");
-   indentation++;
-
-   foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
-      ir_instruction *const inst = (ir_instruction *) iter.get();
-
-      indent();
-      inst->accept(this);
-      printf("\n");
-   }
-   indentation--;
-   indent();
-   printf("))\n");
-}
-
-
-void
-ir_print_visitor::visit(ir_loop_jump *ir)
-{
-   printf("%s", ir->is_break() ? "break" : "continue");
-}
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "ir_print_visitor.h"
+#include "glsl_types.h"
+#include "glsl_parser_extras.h"
+
+extern "C" {
+#include "program/hash_table.h"
+}
+
+static void print_type(const glsl_type *t);
+
+void
+ir_instruction::print(void) const
+{
+   ir_instruction *deconsted = const_cast<ir_instruction *>(this);
+
+   ir_print_visitor v;
+   deconsted->accept(&v);
+}
+
+void
+_mesa_print_ir(exec_list *instructions,
+	       struct _mesa_glsl_parse_state *state)
+{
+   if (state) {
+      for (unsigned i = 0; i < state->num_user_structures; i++) {
+	 const glsl_type *const s = state->user_structures[i];
+
+	 printf("(structure (%s) (%s@%p) (%u) (\n",
+		s->name, s->name, (void *) s, s->length);
+
+	 for (unsigned j = 0; j < s->length; j++) {
+	    printf("\t((");
+	    print_type(s->fields.structure[j].type);
+	    printf(")(%s))\n", s->fields.structure[j].name);
+	 }
+
+	 printf(")\n");
+      }
+   }
+
+   printf("(\n");
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+      ir->print();
+      if (ir->ir_type != ir_type_function)
+	 printf("\n");
+   }
+   printf("\n)");
+}
+
+ir_print_visitor::ir_print_visitor()
+{
+   indentation = 0;
+   printable_names =
+      hash_table_ctor(32, hash_table_pointer_hash, hash_table_pointer_compare);
+   symbols = _mesa_symbol_table_ctor();
+   mem_ctx = ralloc_context(NULL);
+}
+
+ir_print_visitor::~ir_print_visitor()
+{
+   hash_table_dtor(printable_names);
+   _mesa_symbol_table_dtor(symbols);
+   ralloc_free(mem_ctx);
+}
+
+void ir_print_visitor::indent(void)
+{
+   for (int i = 0; i < indentation; i++)
+      printf("  ");
+}
+
+const char *
+ir_print_visitor::unique_name(ir_variable *var)
+{
+   /* Do we already have a name for this variable? */
+   const char *name = (const char *) hash_table_find(this->printable_names, var);
+   if (name != NULL)
+      return name;
+
+   /* If there's no conflict, just use the original name */
+   if (_mesa_symbol_table_find_symbol(this->symbols, -1, var->name) == NULL) {
+      name = var->name;
+   } else {
+      static unsigned i = 1;
+      name = ralloc_asprintf(this->mem_ctx, "%s@%u", var->name, ++i);
+   }
+   hash_table_insert(this->printable_names, (void *) name, var);
+   _mesa_symbol_table_add_symbol(this->symbols, -1, name, var);
+   return name;
+}
+
+static void
+print_type(const glsl_type *t)
+{
+   if (t->base_type == GLSL_TYPE_ARRAY) {
+      printf("(array ");
+      print_type(t->fields.array);
+      printf(" %u)", t->length);
+   } else if ((t->base_type == GLSL_TYPE_STRUCT)
+	      && (strncmp("gl_", t->name, 3) != 0)) {
+      printf("%s@%p", t->name, (void *) t);
+   } else {
+      printf("%s", t->name);
+   }
+}
+
+
+void ir_print_visitor::visit(ir_variable *ir)
+{
+   printf("(declare ");
+
+   const char *const cent = (ir->centroid) ? "centroid " : "";
+   const char *const inv = (ir->invariant) ? "invariant " : "";
+   const char *const mode[] = { "", "uniform ", "in ", "out ", "inout ",
+			        "const_in ", "sys ", "temporary " };
+   const char *const interp[] = { "", "flat", "noperspective" };
+
+   printf("(%s%s%s%s) ",
+	  cent, inv, mode[ir->mode], interp[ir->interpolation]);
+
+   print_type(ir->type);
+   printf(" %s)", unique_name(ir));
+}
+
+
+void ir_print_visitor::visit(ir_function_signature *ir)
+{
+   _mesa_symbol_table_push_scope(symbols);
+   printf("(signature ");
+   indentation++;
+
+   print_type(ir->return_type);
+   printf("\n");
+   indent();
+
+   printf("(parameters\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->parameters) {
+      ir_variable *const inst = (ir_variable *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+   indentation--;
+
+   indent();
+   printf(")\n");
+
+   indent();
+
+   printf("(\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->body) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+   indentation--;
+   indent();
+   printf("))\n");
+   indentation--;
+   _mesa_symbol_table_pop_scope(symbols);
+}
+
+
+void ir_print_visitor::visit(ir_function *ir)
+{
+   printf("(function %s\n", ir->name);
+   indentation++;
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_function_signature *const sig = (ir_function_signature *) iter.get();
+      indent();
+      sig->accept(this);
+      printf("\n");
+   }
+   indentation--;
+   indent();
+   printf(")\n\n");
+}
+
+
+void ir_print_visitor::visit(ir_expression *ir)
+{
+   printf("(expression ");
+
+   print_type(ir->type);
+
+   printf(" %s ", ir->operator_string());
+
+   for (unsigned i = 0; i < ir->get_num_operands(); i++) {
+      ir->operands[i]->accept(this);
+   }
+
+   printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_texture *ir)
+{
+   printf("(%s ", ir->opcode_string());
+
+   print_type(ir->type);
+   printf(" ");
+
+   ir->sampler->accept(this);
+   printf(" ");
+
+   ir->coordinate->accept(this);
+
+   printf(" ");
+
+   if (ir->offset != NULL) {
+      ir->offset->accept(this);
+   } else {
+      printf("0");
+   }
+
+   printf(" ");
+
+   if (ir->op != ir_txf) {
+      if (ir->projector)
+	 ir->projector->accept(this);
+      else
+	 printf("1");
+
+      if (ir->shadow_comparitor) {
+	 printf(" ");
+	 ir->shadow_comparitor->accept(this);
+      } else {
+	 printf(" ()");
+      }
+   }
+
+   printf(" ");
+   switch (ir->op)
+   {
+   case ir_tex:
+      break;
+   case ir_txb:
+      ir->lod_info.bias->accept(this);
+      break;
+   case ir_txl:
+   case ir_txf:
+      ir->lod_info.lod->accept(this);
+      break;
+   case ir_txd:
+      printf("(");
+      ir->lod_info.grad.dPdx->accept(this);
+      printf(" ");
+      ir->lod_info.grad.dPdy->accept(this);
+      printf(")");
+      break;
+   };
+   printf(")");
+}
+
+
+void ir_print_visitor::visit(ir_swizzle *ir)
+{
+   const unsigned swiz[4] = {
+      ir->mask.x,
+      ir->mask.y,
+      ir->mask.z,
+      ir->mask.w,
+   };
+
+   printf("(swiz ");
+   for (unsigned i = 0; i < ir->mask.num_components; i++) {
+      printf("%c", "xyzw"[swiz[i]]);
+   }
+   printf(" ");
+   ir->val->accept(this);
+   printf(")");
+}
+
+
+void ir_print_visitor::visit(ir_dereference_variable *ir)
+{
+   ir_variable *var = ir->variable_referenced();
+   printf("(var_ref %s) ", unique_name(var));
+}
+
+
+void ir_print_visitor::visit(ir_dereference_array *ir)
+{
+   printf("(array_ref ");
+   ir->array->accept(this);
+   ir->array_index->accept(this);
+   printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_dereference_record *ir)
+{
+   printf("(record_ref ");
+   ir->record->accept(this);
+   printf(" %s) ", ir->field);
+}
+
+
+void ir_print_visitor::visit(ir_assignment *ir)
+{
+   printf("(assign ");
+
+   if (ir->condition)
+      ir->condition->accept(this);
+
+   char mask[5];
+   unsigned j = 0;
+
+   for (unsigned i = 0; i < 4; i++) {
+      if ((ir->write_mask & (1 << i)) != 0) {
+	 mask[j] = "xyzw"[i];
+	 j++;
+      }
+   }
+   mask[j] = '\0';
+
+   printf(" (%s) ", mask);
+
+   ir->lhs->accept(this);
+
+   printf(" ");
+
+   ir->rhs->accept(this);
+   printf(") ");
+}
+
+
+void ir_print_visitor::visit(ir_constant *ir)
+{
+   const glsl_type *const base_type = ir->type->get_base_type();
+
+   printf("(constant ");
+   print_type(ir->type);
+   printf(" (");
+
+   if (ir->type->is_array()) {
+      for (unsigned i = 0; i < ir->type->length; i++)
+	 ir->get_array_element(i)->accept(this);
+   } else if (ir->type->is_record()) {
+      ir_constant *value = (ir_constant *) ir->components.get_head();
+      for (unsigned i = 0; i < ir->type->length; i++) {
+	 printf("(%s ", ir->type->fields.structure->name);
+	 value->accept(this);
+	 printf(")");
+
+	 value = (ir_constant *) value->next;
+      }
+   } else {
+      for (unsigned i = 0; i < ir->type->components(); i++) {
+	 if (i != 0)
+	    printf(" ");
+	 switch (base_type->base_type) {
+	 case GLSL_TYPE_UINT:  printf("%u", ir->value.u[i]); break;
+	 case GLSL_TYPE_INT:   printf("%d", ir->value.i[i]); break;
+	 case GLSL_TYPE_FLOAT: printf("%f", ir->value.f[i]); break;
+	 case GLSL_TYPE_BOOL:  printf("%d", ir->value.b[i]); break;
+	 default: assert(0);
+	 }
+      }
+   }
+   printf(")) ");
+}
+
+
+void
+ir_print_visitor::visit(ir_call *ir)
+{
+   printf("(call %s (", ir->callee_name());
+   foreach_iter(exec_list_iterator, iter, *ir) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      inst->accept(this);
+   }
+   printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_return *ir)
+{
+   printf("(return");
+
+   ir_rvalue *const value = ir->get_value();
+   if (value) {
+      printf(" ");
+      value->accept(this);
+   }
+
+   printf(")");
+}
+
+
+void
+ir_print_visitor::visit(ir_discard *ir)
+{
+   printf("(discard ");
+
+   if (ir->condition != NULL) {
+      printf(" ");
+      ir->condition->accept(this);
+   }
+
+   printf(")");
+}
+
+
+void
+ir_print_visitor::visit(ir_if *ir)
+{
+   printf("(if ");
+   ir->condition->accept(this);
+
+   printf("(\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->then_instructions) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+
+   indentation--;
+   indent();
+   printf(")\n");
+
+   indent();
+   if (!ir->else_instructions.is_empty()) {
+      printf("(\n");
+      indentation++;
+
+      foreach_iter(exec_list_iterator, iter, ir->else_instructions) {
+	 ir_instruction *const inst = (ir_instruction *) iter.get();
+
+	 indent();
+	 inst->accept(this);
+	 printf("\n");
+      }
+      indentation--;
+      indent();
+      printf("))\n");
+   } else {
+      printf("())\n");
+   }
+}
+
+
+void
+ir_print_visitor::visit(ir_loop *ir)
+{
+   printf("(loop (");
+   if (ir->counter != NULL)
+      ir->counter->accept(this);
+   printf(") (");
+   if (ir->from != NULL)
+      ir->from->accept(this);
+   printf(") (");
+   if (ir->to != NULL)
+      ir->to->accept(this);
+   printf(") (");
+   if (ir->increment != NULL)
+      ir->increment->accept(this);
+   printf(") (\n");
+   indentation++;
+
+   foreach_iter(exec_list_iterator, iter, ir->body_instructions) {
+      ir_instruction *const inst = (ir_instruction *) iter.get();
+
+      indent();
+      inst->accept(this);
+      printf("\n");
+   }
+   indentation--;
+   indent();
+   printf("))\n");
+}
+
+
+void
+ir_print_visitor::visit(ir_loop_jump *ir)
+{
+   printf("%s", ir->is_break() ? "break" : "continue");
+}
diff --git a/mesalib/src/glsl/ir_print_visitor.h b/mesalib/src/glsl/ir_print_visitor.h
index 4feeb8c18..c7136f11a 100644
--- a/mesalib/src/glsl/ir_print_visitor.h
+++ b/mesalib/src/glsl/ir_print_visitor.h
@@ -29,6 +29,10 @@
 #include "ir.h"
 #include "ir_visitor.h"
 
+extern "C" {
+#include "program/symbol_table.h"
+}
+
 extern void _mesa_print_ir(exec_list *instructions,
 			   struct _mesa_glsl_parse_state *state);
 
@@ -37,15 +41,8 @@ extern void _mesa_print_ir(exec_list *instructions,
  */
 class ir_print_visitor : public ir_visitor {
 public:
-   ir_print_visitor()
-   {
-      indentation = 0;
-   }
-
-   virtual ~ir_print_visitor()
-   {
-      /* empty */
-   }
+   ir_print_visitor();
+   virtual ~ir_print_visitor();
 
    void indent(void);
 
@@ -77,6 +74,20 @@ public:
    /*@}*/
 
 private:
+   /**
+    * Fetch/generate a unique name for ir_variable.
+    *
+    * GLSL IR permits multiple ir_variables to share the same name.  This works
+    * fine until we try to print it, when we really need a unique one.
+    */
+   const char *unique_name(ir_variable *var);
+
+   /** A mapping from ir_variable * -> unique printable names. */
+   hash_table *printable_names;
+   _mesa_symbol_table *symbols;
+
+   void *mem_ctx;
+
    int indentation;
 };
 
diff --git a/mesalib/src/glsl/ir_validate.cpp b/mesalib/src/glsl/ir_validate.cpp
index fe6ef8145..ec79d05ca 100644
--- a/mesalib/src/glsl/ir_validate.cpp
+++ b/mesalib/src/glsl/ir_validate.cpp
@@ -1,562 +1,577 @@
-/*
- * Copyright © 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file ir_validate.cpp
- *
- * Attempts to verify that various invariants of the IR tree are true.
- *
- * In particular, at the moment it makes sure that no single
- * ir_instruction node except for ir_variable appears multiple times
- * in the ir tree.  ir_variable does appear multiple times: Once as a
- * declaration in an exec_list, and multiple times as the endpoint of
- * a dereference chain.
- */
-
-#include <inttypes.h>
-#include "ir.h"
-#include "ir_hierarchical_visitor.h"
-#include "program/hash_table.h"
-#include "glsl_types.h"
-
-class ir_validate : public ir_hierarchical_visitor {
-public:
-   ir_validate()
-   {
-      this->ht = hash_table_ctor(0, hash_table_pointer_hash,
-				 hash_table_pointer_compare);
-
-      this->current_function = NULL;
-
-      this->callback = ir_validate::validate_ir;
-      this->data = ht;
-   }
-
-   ~ir_validate()
-   {
-      hash_table_dtor(this->ht);
-   }
-
-   virtual ir_visitor_status visit(ir_variable *v);
-   virtual ir_visitor_status visit(ir_dereference_variable *ir);
-   virtual ir_visitor_status visit(ir_if *ir);
-
-   virtual ir_visitor_status visit_leave(ir_loop *ir);
-   virtual ir_visitor_status visit_enter(ir_function *ir);
-   virtual ir_visitor_status visit_leave(ir_function *ir);
-   virtual ir_visitor_status visit_enter(ir_function_signature *ir);
-
-   virtual ir_visitor_status visit_leave(ir_expression *ir);
-   virtual ir_visitor_status visit_leave(ir_swizzle *ir);
-
-   virtual ir_visitor_status visit_enter(ir_assignment *ir);
-   virtual ir_visitor_status visit_enter(ir_call *ir);
-
-   static void validate_ir(ir_instruction *ir, void *data);
-
-   ir_function *current_function;
-
-   struct hash_table *ht;
-};
-
-
-ir_visitor_status
-ir_validate::visit(ir_dereference_variable *ir)
-{
-   if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
-      printf("ir_dereference_variable @ %p does not specify a variable %p\n",
-	     (void *) ir, (void *) ir->var);
-      abort();
-   }
-
-   if (hash_table_find(ht, ir->var) == NULL) {
-      printf("ir_dereference_variable @ %p specifies undeclared variable "
-	     "`%s' @ %p\n",
-	     (void *) ir, ir->var->name, (void *) ir->var);
-      abort();
-   }
-
-   this->validate_ir(ir, this->data);
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit(ir_if *ir)
-{
-   if (ir->condition->type != glsl_type::bool_type) {
-      printf("ir_if condition %s type instead of bool.\n",
-	     ir->condition->type->name);
-      ir->print();
-      printf("\n");
-      abort();
-   }
-
-   return visit_continue;
-}
-
-
-ir_visitor_status
-ir_validate::visit_leave(ir_loop *ir)
-{
-   if (ir->counter != NULL) {
-      if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) {
-	 printf("ir_loop has invalid loop controls:\n"
-		"    counter:   %p\n"
-		"    from:      %p\n"
-		"    to:        %p\n"
-		"    increment: %p\n",
-		(void *) ir->counter, (void *) ir->from, (void *) ir->to,
-                (void *) ir->increment);
-	 abort();
-      }
-
-      if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) {
-	 printf("ir_loop has invalid comparitor %d\n", ir->cmp);
-	 abort();
-      }
-   } else {
-      if ((ir->from != NULL) || (ir->from != NULL) || (ir->increment != NULL)) {
-	 printf("ir_loop has invalid loop controls:\n"
-		"    counter:   %p\n"
-		"    from:      %p\n"
-		"    to:        %p\n"
-		"    increment: %p\n",
-		(void *) ir->counter, (void *) ir->from, (void *) ir->to,
-                (void *) ir->increment);
-	 abort();
-      }
-   }
-
-   return visit_continue;
-}
-
-
-ir_visitor_status
-ir_validate::visit_enter(ir_function *ir)
-{
-   /* Function definitions cannot be nested.
-    */
-   if (this->current_function != NULL) {
-      printf("Function definition nested inside another function "
-	     "definition:\n");
-      printf("%s %p inside %s %p\n",
-	     ir->name, (void *) ir,
-	     this->current_function->name, (void *) this->current_function);
-      abort();
-   }
-
-   /* Store the current function hierarchy being traversed.  This is used
-    * by the function signature visitor to ensure that the signatures are
-    * linked with the correct functions.
-    */
-   this->current_function = ir;
-
-   this->validate_ir(ir, this->data);
-
-   /* Verify that all of the things stored in the list of signatures are,
-    * in fact, function signatures.
-    */
-   foreach_list(node, &ir->signatures) {
-      ir_instruction *sig = (ir_instruction *) node;
-
-      if (sig->ir_type != ir_type_function_signature) {
-	 printf("Non-signature in signature list of function `%s'\n",
-		ir->name);
-	 abort();
-      }
-   }
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit_leave(ir_function *ir)
-{
-   assert(ralloc_parent(ir->name) == ir);
-
-   this->current_function = NULL;
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit_enter(ir_function_signature *ir)
-{
-   if (this->current_function != ir->function()) {
-      printf("Function signature nested inside wrong function "
-	     "definition:\n");
-      printf("%p inside %s %p instead of %s %p\n",
-	     (void *) ir,
-	     this->current_function->name, (void *) this->current_function,
-	     ir->function_name(), (void *) ir->function());
-      abort();
-   }
-
-   if (ir->return_type == NULL) {
-      printf("Function signature %p for function %s has NULL return type.\n",
-	     (void *) ir, ir->function_name());
-      abort();
-   }
-
-   this->validate_ir(ir, this->data);
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit_leave(ir_expression *ir)
-{
-   switch (ir->operation) {
-   case ir_unop_bit_not:
-      assert(ir->operands[0]->type == ir->type);
-      break;
-   case ir_unop_logic_not:
-      assert(ir->type->base_type == GLSL_TYPE_BOOL);
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
-      break;
-
-   case ir_unop_neg:
-   case ir_unop_abs:
-   case ir_unop_sign:
-   case ir_unop_rcp:
-   case ir_unop_rsq:
-   case ir_unop_sqrt:
-      assert(ir->type == ir->operands[0]->type);
-      break;
-
-   case ir_unop_exp:
-   case ir_unop_log:
-   case ir_unop_exp2:
-   case ir_unop_log2:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
-      assert(ir->type == ir->operands[0]->type);
-      break;
-
-   case ir_unop_f2i:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
-      assert(ir->type->base_type == GLSL_TYPE_INT);
-      break;
-   case ir_unop_i2f:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
-      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
-      break;
-   case ir_unop_f2b:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
-      assert(ir->type->base_type == GLSL_TYPE_BOOL);
-      break;
-   case ir_unop_b2f:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
-      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
-      break;
-   case ir_unop_i2b:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
-      assert(ir->type->base_type == GLSL_TYPE_BOOL);
-      break;
-   case ir_unop_b2i:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
-      assert(ir->type->base_type == GLSL_TYPE_INT);
-      break;
-   case ir_unop_u2f:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
-      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
-      break;
-
-   case ir_unop_any:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
-      assert(ir->type == glsl_type::bool_type);
-      break;
-
-   case ir_unop_trunc:
-   case ir_unop_round_even:
-   case ir_unop_ceil:
-   case ir_unop_floor:
-   case ir_unop_fract:
-   case ir_unop_sin:
-   case ir_unop_cos:
-   case ir_unop_sin_reduced:
-   case ir_unop_cos_reduced:
-   case ir_unop_dFdx:
-   case ir_unop_dFdy:
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
-      assert(ir->operands[0]->type == ir->type);
-      break;
-
-   case ir_unop_noise:
-      /* XXX what can we assert here? */
-      break;
-
-   case ir_binop_add:
-   case ir_binop_sub:
-   case ir_binop_mul:
-   case ir_binop_div:
-   case ir_binop_mod:
-   case ir_binop_min:
-   case ir_binop_max:
-   case ir_binop_pow:
-      if (ir->operands[0]->type->is_scalar())
-	 assert(ir->operands[1]->type == ir->type);
-      else if (ir->operands[1]->type->is_scalar())
-	 assert(ir->operands[0]->type == ir->type);
-      else if (ir->operands[0]->type->is_vector() &&
-	       ir->operands[1]->type->is_vector()) {
-	 assert(ir->operands[0]->type == ir->operands[1]->type);
-	 assert(ir->operands[0]->type == ir->type);
-      }
-      break;
-
-   case ir_binop_less:
-   case ir_binop_greater:
-   case ir_binop_lequal:
-   case ir_binop_gequal:
-   case ir_binop_equal:
-   case ir_binop_nequal:
-      /* The semantics of the IR operators differ from the GLSL <, >, <=, >=,
-       * ==, and != operators.  The IR operators perform a component-wise
-       * comparison on scalar or vector types and return a boolean scalar or
-       * vector type of the same size.
-       */
-      assert(ir->type->base_type == GLSL_TYPE_BOOL);
-      assert(ir->operands[0]->type == ir->operands[1]->type);
-      assert(ir->operands[0]->type->is_vector()
-	     || ir->operands[0]->type->is_scalar());
-      assert(ir->operands[0]->type->vector_elements
-	     == ir->type->vector_elements);
-      break;
-
-   case ir_binop_all_equal:
-   case ir_binop_any_nequal:
-      /* GLSL == and != operate on scalars, vectors, matrices and arrays, and
-       * return a scalar boolean.  The IR matches that.
-       */
-      assert(ir->type == glsl_type::bool_type);
-      assert(ir->operands[0]->type == ir->operands[1]->type);
-      break;
-
-   case ir_binop_lshift:
-   case ir_binop_rshift:
-      assert(ir->operands[0]->type->is_integer() &&
-             ir->operands[1]->type->is_integer());
-      if (ir->operands[0]->type->is_scalar()) {
-          assert(ir->operands[1]->type->is_scalar());
-      }
-      if (ir->operands[0]->type->is_vector() &&
-          ir->operands[1]->type->is_vector()) {
-          assert(ir->operands[0]->type->components() ==
-                 ir->operands[1]->type->components());
-      }
-      assert(ir->type == ir->operands[0]->type);
-      break;
-
-   case ir_binop_bit_and:
-   case ir_binop_bit_xor:
-   case ir_binop_bit_or:
-       assert(ir->operands[0]->type->base_type ==
-              ir->operands[1]->type->base_type);
-       assert(ir->type->is_integer());
-       if (ir->operands[0]->type->is_vector() &&
-           ir->operands[1]->type->is_vector()) {
-           assert(ir->operands[0]->type->vector_elements ==
-                  ir->operands[1]->type->vector_elements);
-       }
-       break;
-
-   case ir_binop_logic_and:
-   case ir_binop_logic_xor:
-   case ir_binop_logic_or:
-      assert(ir->type == glsl_type::bool_type);
-      assert(ir->operands[0]->type == glsl_type::bool_type);
-      assert(ir->operands[1]->type == glsl_type::bool_type);
-      break;
-
-   case ir_binop_dot:
-      assert(ir->type == glsl_type::float_type);
-      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
-      assert(ir->operands[0]->type->is_vector());
-      assert(ir->operands[0]->type == ir->operands[1]->type);
-      break;
-
-   case ir_quadop_vector:
-      /* The vector operator collects some number of scalars and generates a
-       * vector from them.
-       *
-       *  - All of the operands must be scalar.
-       *  - Number of operands must matche the size of the resulting vector.
-       *  - Base type of the operands must match the base type of the result.
-       */
-      assert(ir->type->is_vector());
-      switch (ir->type->vector_elements) {
-      case 2:
-	 assert(ir->operands[0]->type->is_scalar());
-	 assert(ir->operands[0]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[1]->type->is_scalar());
-	 assert(ir->operands[1]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[2] == NULL);
-	 assert(ir->operands[3] == NULL);
-	 break;
-      case 3:
-	 assert(ir->operands[0]->type->is_scalar());
-	 assert(ir->operands[0]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[1]->type->is_scalar());
-	 assert(ir->operands[1]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[2]->type->is_scalar());
-	 assert(ir->operands[2]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[3] == NULL);
-	 break;
-      case 4:
-	 assert(ir->operands[0]->type->is_scalar());
-	 assert(ir->operands[0]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[1]->type->is_scalar());
-	 assert(ir->operands[1]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[2]->type->is_scalar());
-	 assert(ir->operands[2]->type->base_type == ir->type->base_type);
-	 assert(ir->operands[3]->type->is_scalar());
-	 assert(ir->operands[3]->type->base_type == ir->type->base_type);
-	 break;
-      default:
-	 /* The is_vector assertion above should prevent execution from ever
-	  * getting here.
-	  */
-	 assert(!"Should not get here.");
-	 break;
-      }
-   }
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit_leave(ir_swizzle *ir)
-{
-   int chans[4] = {ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w};
-
-   for (unsigned int i = 0; i < ir->type->vector_elements; i++) {
-      if (chans[i] >= ir->val->type->vector_elements) {
-	 printf("ir_swizzle @ %p specifies a channel not present "
-		"in the value.\n", (void *) ir);
-	 ir->print();
-	 abort();
-      }
-   }
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit(ir_variable *ir)
-{
-   /* An ir_variable is the one thing that can (and will) appear multiple times
-    * in an IR tree.  It is added to the hashtable so that it can be used
-    * in the ir_dereference_variable handler to ensure that a variable is
-    * declared before it is dereferenced.
-    */
-   if (ir->name)
-      assert(ralloc_parent(ir->name) == ir);
-
-   hash_table_insert(ht, ir, ir);
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit_enter(ir_assignment *ir)
-{
-   const ir_dereference *const lhs = ir->lhs;
-   if (lhs->type->is_scalar() || lhs->type->is_vector()) {
-      if (ir->write_mask == 0) {
-	 printf("Assignment LHS is %s, but write mask is 0:\n",
-		lhs->type->is_scalar() ? "scalar" : "vector");
-	 ir->print();
-	 abort();
-      }
-
-      int lhs_components = 0;
-      for (int i = 0; i < 4; i++) {
-	 if (ir->write_mask & (1 << i))
-	    lhs_components++;
-      }
-
-      if (lhs_components != ir->rhs->type->vector_elements) {
-	 printf("Assignment count of LHS write mask channels enabled not\n"
-		"matching RHS vector size (%d LHS, %d RHS).\n",
-		lhs_components, ir->rhs->type->vector_elements);
-	 ir->print();
-	 abort();
-      }
-   }
-
-   this->validate_ir(ir, this->data);
-
-   return visit_continue;
-}
-
-ir_visitor_status
-ir_validate::visit_enter(ir_call *ir)
-{
-   ir_function_signature *const callee = ir->get_callee();
-
-   if (callee->ir_type != ir_type_function_signature) {
-      printf("IR called by ir_call is not ir_function_signature!\n");
-      abort();
-   }
-
-   return visit_continue;
-}
-
-void
-ir_validate::validate_ir(ir_instruction *ir, void *data)
-{
-   struct hash_table *ht = (struct hash_table *) data;
-
-   if (hash_table_find(ht, ir)) {
-      printf("Instruction node present twice in ir tree:\n");
-      ir->print();
-      printf("\n");
-      abort();
-   }
-   hash_table_insert(ht, ir, ir);
-}
-
-void
-check_node_type(ir_instruction *ir, void *data)
-{
-   (void) data;
-
-   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
-      printf("Instruction node with unset type\n");
-      ir->print(); printf("\n");
-   }
-   assert(ir->type != glsl_type::error_type);
-}
-
-void
-validate_ir_tree(exec_list *instructions)
-{
-   ir_validate v;
-
-   v.run(instructions);
-
-   foreach_iter(exec_list_iterator, iter, *instructions) {
-      ir_instruction *ir = (ir_instruction *)iter.get();
-
-      visit_tree(ir, check_node_type, NULL);
-   }
-}
+/*
+ * Copyright © 2010 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file ir_validate.cpp
+ *
+ * Attempts to verify that various invariants of the IR tree are true.
+ *
+ * In particular, at the moment it makes sure that no single
+ * ir_instruction node except for ir_variable appears multiple times
+ * in the ir tree.  ir_variable does appear multiple times: Once as a
+ * declaration in an exec_list, and multiple times as the endpoint of
+ * a dereference chain.
+ */
+
+#include <inttypes.h>
+#include "ir.h"
+#include "ir_hierarchical_visitor.h"
+#include "program/hash_table.h"
+#include "glsl_types.h"
+
+class ir_validate : public ir_hierarchical_visitor {
+public:
+   ir_validate()
+   {
+      this->ht = hash_table_ctor(0, hash_table_pointer_hash,
+				 hash_table_pointer_compare);
+
+      this->current_function = NULL;
+
+      this->callback = ir_validate::validate_ir;
+      this->data = ht;
+   }
+
+   ~ir_validate()
+   {
+      hash_table_dtor(this->ht);
+   }
+
+   virtual ir_visitor_status visit(ir_variable *v);
+   virtual ir_visitor_status visit(ir_dereference_variable *ir);
+   virtual ir_visitor_status visit(ir_if *ir);
+
+   virtual ir_visitor_status visit_leave(ir_loop *ir);
+   virtual ir_visitor_status visit_enter(ir_function *ir);
+   virtual ir_visitor_status visit_leave(ir_function *ir);
+   virtual ir_visitor_status visit_enter(ir_function_signature *ir);
+
+   virtual ir_visitor_status visit_leave(ir_expression *ir);
+   virtual ir_visitor_status visit_leave(ir_swizzle *ir);
+
+   virtual ir_visitor_status visit_enter(ir_assignment *ir);
+   virtual ir_visitor_status visit_enter(ir_call *ir);
+
+   static void validate_ir(ir_instruction *ir, void *data);
+
+   ir_function *current_function;
+
+   struct hash_table *ht;
+};
+
+
+ir_visitor_status
+ir_validate::visit(ir_dereference_variable *ir)
+{
+   if ((ir->var == NULL) || (ir->var->as_variable() == NULL)) {
+      printf("ir_dereference_variable @ %p does not specify a variable %p\n",
+	     (void *) ir, (void *) ir->var);
+      abort();
+   }
+
+   if (hash_table_find(ht, ir->var) == NULL) {
+      printf("ir_dereference_variable @ %p specifies undeclared variable "
+	     "`%s' @ %p\n",
+	     (void *) ir, ir->var->name, (void *) ir->var);
+      abort();
+   }
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit(ir_if *ir)
+{
+   if (ir->condition->type != glsl_type::bool_type) {
+      printf("ir_if condition %s type instead of bool.\n",
+	     ir->condition->type->name);
+      ir->print();
+      printf("\n");
+      abort();
+   }
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_validate::visit_leave(ir_loop *ir)
+{
+   if (ir->counter != NULL) {
+      if ((ir->from == NULL) || (ir->from == NULL) || (ir->increment == NULL)) {
+	 printf("ir_loop has invalid loop controls:\n"
+		"    counter:   %p\n"
+		"    from:      %p\n"
+		"    to:        %p\n"
+		"    increment: %p\n",
+		(void *) ir->counter, (void *) ir->from, (void *) ir->to,
+                (void *) ir->increment);
+	 abort();
+      }
+
+      if ((ir->cmp < ir_binop_less) || (ir->cmp > ir_binop_nequal)) {
+	 printf("ir_loop has invalid comparitor %d\n", ir->cmp);
+	 abort();
+      }
+   } else {
+      if ((ir->from != NULL) || (ir->from != NULL) || (ir->increment != NULL)) {
+	 printf("ir_loop has invalid loop controls:\n"
+		"    counter:   %p\n"
+		"    from:      %p\n"
+		"    to:        %p\n"
+		"    increment: %p\n",
+		(void *) ir->counter, (void *) ir->from, (void *) ir->to,
+                (void *) ir->increment);
+	 abort();
+      }
+   }
+
+   return visit_continue;
+}
+
+
+ir_visitor_status
+ir_validate::visit_enter(ir_function *ir)
+{
+   /* Function definitions cannot be nested.
+    */
+   if (this->current_function != NULL) {
+      printf("Function definition nested inside another function "
+	     "definition:\n");
+      printf("%s %p inside %s %p\n",
+	     ir->name, (void *) ir,
+	     this->current_function->name, (void *) this->current_function);
+      abort();
+   }
+
+   /* Store the current function hierarchy being traversed.  This is used
+    * by the function signature visitor to ensure that the signatures are
+    * linked with the correct functions.
+    */
+   this->current_function = ir;
+
+   this->validate_ir(ir, this->data);
+
+   /* Verify that all of the things stored in the list of signatures are,
+    * in fact, function signatures.
+    */
+   foreach_list(node, &ir->signatures) {
+      ir_instruction *sig = (ir_instruction *) node;
+
+      if (sig->ir_type != ir_type_function_signature) {
+	 printf("Non-signature in signature list of function `%s'\n",
+		ir->name);
+	 abort();
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_function *ir)
+{
+   assert(ralloc_parent(ir->name) == ir);
+
+   this->current_function = NULL;
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_enter(ir_function_signature *ir)
+{
+   if (this->current_function != ir->function()) {
+      printf("Function signature nested inside wrong function "
+	     "definition:\n");
+      printf("%p inside %s %p instead of %s %p\n",
+	     (void *) ir,
+	     this->current_function->name, (void *) this->current_function,
+	     ir->function_name(), (void *) ir->function());
+      abort();
+   }
+
+   if (ir->return_type == NULL) {
+      printf("Function signature %p for function %s has NULL return type.\n",
+	     (void *) ir, ir->function_name());
+      abort();
+   }
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_expression *ir)
+{
+   switch (ir->operation) {
+   case ir_unop_bit_not:
+      assert(ir->operands[0]->type == ir->type);
+      break;
+   case ir_unop_logic_not:
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      break;
+
+   case ir_unop_neg:
+   case ir_unop_abs:
+   case ir_unop_sign:
+   case ir_unop_rcp:
+   case ir_unop_rsq:
+   case ir_unop_sqrt:
+      assert(ir->type == ir->operands[0]->type);
+      break;
+
+   case ir_unop_exp:
+   case ir_unop_log:
+   case ir_unop_exp2:
+   case ir_unop_log2:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type == ir->operands[0]->type);
+      break;
+
+   case ir_unop_f2i:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type->base_type == GLSL_TYPE_INT);
+      break;
+   case ir_unop_i2f:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+      break;
+   case ir_unop_f2b:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      break;
+   case ir_unop_b2f:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+      break;
+   case ir_unop_i2b:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_INT);
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      break;
+   case ir_unop_b2i:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->type->base_type == GLSL_TYPE_INT);
+      break;
+   case ir_unop_u2f:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_UINT);
+      assert(ir->type->base_type == GLSL_TYPE_FLOAT);
+      break;
+
+   case ir_unop_any:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->type == glsl_type::bool_type);
+      break;
+
+   case ir_unop_trunc:
+   case ir_unop_round_even:
+   case ir_unop_ceil:
+   case ir_unop_floor:
+   case ir_unop_fract:
+   case ir_unop_sin:
+   case ir_unop_cos:
+   case ir_unop_sin_reduced:
+   case ir_unop_cos_reduced:
+   case ir_unop_dFdx:
+   case ir_unop_dFdy:
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->operands[0]->type == ir->type);
+      break;
+
+   case ir_unop_noise:
+      /* XXX what can we assert here? */
+      break;
+
+   case ir_binop_add:
+   case ir_binop_sub:
+   case ir_binop_mul:
+   case ir_binop_div:
+   case ir_binop_mod:
+   case ir_binop_min:
+   case ir_binop_max:
+   case ir_binop_pow:
+      if (ir->operands[0]->type->is_scalar())
+	 assert(ir->operands[1]->type == ir->type);
+      else if (ir->operands[1]->type->is_scalar())
+	 assert(ir->operands[0]->type == ir->type);
+      else if (ir->operands[0]->type->is_vector() &&
+	       ir->operands[1]->type->is_vector()) {
+	 assert(ir->operands[0]->type == ir->operands[1]->type);
+	 assert(ir->operands[0]->type == ir->type);
+      }
+      break;
+
+   case ir_binop_less:
+   case ir_binop_greater:
+   case ir_binop_lequal:
+   case ir_binop_gequal:
+   case ir_binop_equal:
+   case ir_binop_nequal:
+      /* The semantics of the IR operators differ from the GLSL <, >, <=, >=,
+       * ==, and != operators.  The IR operators perform a component-wise
+       * comparison on scalar or vector types and return a boolean scalar or
+       * vector type of the same size.
+       */
+      assert(ir->type->base_type == GLSL_TYPE_BOOL);
+      assert(ir->operands[0]->type == ir->operands[1]->type);
+      assert(ir->operands[0]->type->is_vector()
+	     || ir->operands[0]->type->is_scalar());
+      assert(ir->operands[0]->type->vector_elements
+	     == ir->type->vector_elements);
+      break;
+
+   case ir_binop_all_equal:
+   case ir_binop_any_nequal:
+      /* GLSL == and != operate on scalars, vectors, matrices and arrays, and
+       * return a scalar boolean.  The IR matches that.
+       */
+      assert(ir->type == glsl_type::bool_type);
+      assert(ir->operands[0]->type == ir->operands[1]->type);
+      break;
+
+   case ir_binop_lshift:
+   case ir_binop_rshift:
+      assert(ir->operands[0]->type->is_integer() &&
+             ir->operands[1]->type->is_integer());
+      if (ir->operands[0]->type->is_scalar()) {
+          assert(ir->operands[1]->type->is_scalar());
+      }
+      if (ir->operands[0]->type->is_vector() &&
+          ir->operands[1]->type->is_vector()) {
+          assert(ir->operands[0]->type->components() ==
+                 ir->operands[1]->type->components());
+      }
+      assert(ir->type == ir->operands[0]->type);
+      break;
+
+   case ir_binop_bit_and:
+   case ir_binop_bit_xor:
+   case ir_binop_bit_or:
+       assert(ir->operands[0]->type->base_type ==
+              ir->operands[1]->type->base_type);
+       assert(ir->type->is_integer());
+       if (ir->operands[0]->type->is_vector() &&
+           ir->operands[1]->type->is_vector()) {
+           assert(ir->operands[0]->type->vector_elements ==
+                  ir->operands[1]->type->vector_elements);
+       }
+       break;
+
+   case ir_binop_logic_and:
+   case ir_binop_logic_xor:
+   case ir_binop_logic_or:
+      assert(ir->type == glsl_type::bool_type);
+      assert(ir->operands[0]->type == glsl_type::bool_type);
+      assert(ir->operands[1]->type == glsl_type::bool_type);
+      break;
+
+   case ir_binop_dot:
+      assert(ir->type == glsl_type::float_type);
+      assert(ir->operands[0]->type->base_type == GLSL_TYPE_FLOAT);
+      assert(ir->operands[0]->type->is_vector());
+      assert(ir->operands[0]->type == ir->operands[1]->type);
+      break;
+
+   case ir_quadop_vector:
+      /* The vector operator collects some number of scalars and generates a
+       * vector from them.
+       *
+       *  - All of the operands must be scalar.
+       *  - Number of operands must matche the size of the resulting vector.
+       *  - Base type of the operands must match the base type of the result.
+       */
+      assert(ir->type->is_vector());
+      switch (ir->type->vector_elements) {
+      case 2:
+	 assert(ir->operands[0]->type->is_scalar());
+	 assert(ir->operands[0]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[1]->type->is_scalar());
+	 assert(ir->operands[1]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[2] == NULL);
+	 assert(ir->operands[3] == NULL);
+	 break;
+      case 3:
+	 assert(ir->operands[0]->type->is_scalar());
+	 assert(ir->operands[0]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[1]->type->is_scalar());
+	 assert(ir->operands[1]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[2]->type->is_scalar());
+	 assert(ir->operands[2]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[3] == NULL);
+	 break;
+      case 4:
+	 assert(ir->operands[0]->type->is_scalar());
+	 assert(ir->operands[0]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[1]->type->is_scalar());
+	 assert(ir->operands[1]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[2]->type->is_scalar());
+	 assert(ir->operands[2]->type->base_type == ir->type->base_type);
+	 assert(ir->operands[3]->type->is_scalar());
+	 assert(ir->operands[3]->type->base_type == ir->type->base_type);
+	 break;
+      default:
+	 /* The is_vector assertion above should prevent execution from ever
+	  * getting here.
+	  */
+	 assert(!"Should not get here.");
+	 break;
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_leave(ir_swizzle *ir)
+{
+   int chans[4] = {ir->mask.x, ir->mask.y, ir->mask.z, ir->mask.w};
+
+   for (unsigned int i = 0; i < ir->type->vector_elements; i++) {
+      if (chans[i] >= ir->val->type->vector_elements) {
+	 printf("ir_swizzle @ %p specifies a channel not present "
+		"in the value.\n", (void *) ir);
+	 ir->print();
+	 abort();
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit(ir_variable *ir)
+{
+   /* An ir_variable is the one thing that can (and will) appear multiple times
+    * in an IR tree.  It is added to the hashtable so that it can be used
+    * in the ir_dereference_variable handler to ensure that a variable is
+    * declared before it is dereferenced.
+    */
+   if (ir->name)
+      assert(ralloc_parent(ir->name) == ir);
+
+   hash_table_insert(ht, ir, ir);
+
+
+   /* If a variable is an array, verify that the maximum array index is in
+    * bounds.  There was once an error in AST-to-HIR conversion that set this
+    * to be out of bounds.
+    */
+   if (ir->type->array_size() > 0) {
+      if (ir->max_array_access >= ir->type->length) {
+	 printf("ir_variable has maximum access out of bounds (%d vs %d)\n",
+		ir->max_array_access, ir->type->length - 1);
+	 ir->print();
+	 abort();
+      }
+   }
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_enter(ir_assignment *ir)
+{
+   const ir_dereference *const lhs = ir->lhs;
+   if (lhs->type->is_scalar() || lhs->type->is_vector()) {
+      if (ir->write_mask == 0) {
+	 printf("Assignment LHS is %s, but write mask is 0:\n",
+		lhs->type->is_scalar() ? "scalar" : "vector");
+	 ir->print();
+	 abort();
+      }
+
+      int lhs_components = 0;
+      for (int i = 0; i < 4; i++) {
+	 if (ir->write_mask & (1 << i))
+	    lhs_components++;
+      }
+
+      if (lhs_components != ir->rhs->type->vector_elements) {
+	 printf("Assignment count of LHS write mask channels enabled not\n"
+		"matching RHS vector size (%d LHS, %d RHS).\n",
+		lhs_components, ir->rhs->type->vector_elements);
+	 ir->print();
+	 abort();
+      }
+   }
+
+   this->validate_ir(ir, this->data);
+
+   return visit_continue;
+}
+
+ir_visitor_status
+ir_validate::visit_enter(ir_call *ir)
+{
+   ir_function_signature *const callee = ir->get_callee();
+
+   if (callee->ir_type != ir_type_function_signature) {
+      printf("IR called by ir_call is not ir_function_signature!\n");
+      abort();
+   }
+
+   return visit_continue;
+}
+
+void
+ir_validate::validate_ir(ir_instruction *ir, void *data)
+{
+   struct hash_table *ht = (struct hash_table *) data;
+
+   if (hash_table_find(ht, ir)) {
+      printf("Instruction node present twice in ir tree:\n");
+      ir->print();
+      printf("\n");
+      abort();
+   }
+   hash_table_insert(ht, ir, ir);
+}
+
+void
+check_node_type(ir_instruction *ir, void *data)
+{
+   (void) data;
+
+   if (ir->ir_type <= ir_type_unset || ir->ir_type >= ir_type_max) {
+      printf("Instruction node with unset type\n");
+      ir->print(); printf("\n");
+   }
+   assert(ir->type != glsl_type::error_type);
+}
+
+void
+validate_ir_tree(exec_list *instructions)
+{
+   ir_validate v;
+
+   v.run(instructions);
+
+   foreach_iter(exec_list_iterator, iter, *instructions) {
+      ir_instruction *ir = (ir_instruction *)iter.get();
+
+      visit_tree(ir, check_node_type, NULL);
+   }
+}
diff --git a/mesalib/src/glsl/ir_variable.cpp b/mesalib/src/glsl/ir_variable.cpp
index 18a3e0fb0..68d9ab205 100644
--- a/mesalib/src/glsl/ir_variable.cpp
+++ b/mesalib/src/glsl/ir_variable.cpp
@@ -36,9 +36,9 @@ generate_ARB_draw_instanced_variables(exec_list *,
                                       bool, _mesa_glsl_parser_targets);
 
 static ir_variable *
-add_variable(const char *name, enum ir_variable_mode mode, int slot,
-	     const glsl_type *type, exec_list *instructions,
-		     glsl_symbol_table *symtab)
+add_variable(exec_list *instructions, glsl_symbol_table *symtab,
+	     const char *name, const glsl_type *type,
+	     enum ir_variable_mode mode, int slot)
 {
    ir_variable *var = new(symtab) ir_variable(type, name, mode);
 
@@ -71,17 +71,15 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot,
 }
 
 static ir_variable *
-add_uniform(exec_list *instructions,
-	    struct _mesa_glsl_parse_state *state,
+add_uniform(exec_list *instructions, glsl_symbol_table *symtab,
 	    const char *name, const glsl_type *type)
 {
-   return add_variable(name, ir_var_uniform, -1, type, instructions,
-		       state->symbols);
+   return add_variable(instructions, symtab, name, type, ir_var_uniform, -1);
 }
 
 static void
-add_builtin_variable(const builtin_variable *proto, exec_list *instructions,
-		     glsl_symbol_table *symtab)
+add_builtin_variable(exec_list *instructions, glsl_symbol_table *symtab,
+		     const builtin_variable *proto)
 {
    /* Create a new variable declaration from the description supplied by
     * the caller.
@@ -90,18 +88,17 @@ add_builtin_variable(const builtin_variable *proto, exec_list *instructions,
 
    assert(type != NULL);
 
-   add_variable(proto->name, proto->mode, proto->slot, type, instructions,
-		symtab);
+   add_variable(instructions, symtab, proto->name, type, proto->mode,
+		proto->slot);
 }
 
 static void
-add_builtin_constant(exec_list *instructions,
-		     struct _mesa_glsl_parse_state *state,
+add_builtin_constant(exec_list *instructions, glsl_symbol_table *symtab,
 		     const char *name, int value)
 {
-   ir_variable *const var = add_variable(name, ir_var_auto,
-					 -1, glsl_type::int_type,
-					 instructions, state->symbols);
+   ir_variable *const var = add_variable(instructions, symtab,
+					 name, glsl_type::int_type,
+					 ir_var_auto, -1);
    var->constant_value = new(var) ir_constant(value);
 }
 
@@ -112,22 +109,24 @@ static void
 generate_100ES_uniforms(exec_list *instructions,
 		     struct _mesa_glsl_parse_state *state)
 {
-   add_builtin_constant(instructions, state, "gl_MaxVertexAttribs",
+   glsl_symbol_table *const symtab = state->symbols;
+
+   add_builtin_constant(instructions, symtab, "gl_MaxVertexAttribs",
 			state->Const.MaxVertexAttribs);
-   add_builtin_constant(instructions, state, "gl_MaxVertexUniformVectors",
+   add_builtin_constant(instructions, symtab, "gl_MaxVertexUniformVectors",
 			state->Const.MaxVertexUniformComponents);
-   add_builtin_constant(instructions, state, "gl_MaxVaryingVectors",
+   add_builtin_constant(instructions, symtab, "gl_MaxVaryingVectors",
 			state->Const.MaxVaryingFloats / 4);
-   add_builtin_constant(instructions, state, "gl_MaxVertexTextureImageUnits",
+   add_builtin_constant(instructions, symtab, "gl_MaxVertexTextureImageUnits",
 			state->Const.MaxVertexTextureImageUnits);
-   add_builtin_constant(instructions, state, "gl_MaxCombinedTextureImageUnits",
+   add_builtin_constant(instructions, symtab, "gl_MaxCombinedTextureImageUnits",
 			state->Const.MaxCombinedTextureImageUnits);
-   add_builtin_constant(instructions, state, "gl_MaxTextureImageUnits",
+   add_builtin_constant(instructions, symtab, "gl_MaxTextureImageUnits",
 			state->Const.MaxTextureImageUnits);
-   add_builtin_constant(instructions, state, "gl_MaxFragmentUniformVectors",
+   add_builtin_constant(instructions, symtab, "gl_MaxFragmentUniformVectors",
 			state->Const.MaxFragmentUniformComponents);
 
-   add_uniform(instructions, state, "gl_DepthRange",
+   add_uniform(instructions, symtab, "gl_DepthRange",
 	       state->symbols->get_type("gl_DepthRangeParameters"));
 }
 
@@ -135,95 +134,97 @@ static void
 generate_110_uniforms(exec_list *instructions,
 		      struct _mesa_glsl_parse_state *state)
 {
+   glsl_symbol_table *const symtab = state->symbols;
+
    for (unsigned i = 0
 	   ; i < Elements(builtin_110_deprecated_uniforms)
 	   ; i++) {
-      add_builtin_variable(& builtin_110_deprecated_uniforms[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, symtab,
+			   & builtin_110_deprecated_uniforms[i]);
    }
 
-   add_builtin_constant(instructions, state, "gl_MaxLights",
+   add_builtin_constant(instructions, symtab, "gl_MaxLights",
 			state->Const.MaxLights);
-   add_builtin_constant(instructions, state, "gl_MaxClipPlanes",
+   add_builtin_constant(instructions, symtab, "gl_MaxClipPlanes",
 			state->Const.MaxClipPlanes);
-   add_builtin_constant(instructions, state, "gl_MaxTextureUnits",
+   add_builtin_constant(instructions, symtab, "gl_MaxTextureUnits",
 			state->Const.MaxTextureUnits);
-   add_builtin_constant(instructions, state, "gl_MaxTextureCoords",
+   add_builtin_constant(instructions, symtab, "gl_MaxTextureCoords",
 			state->Const.MaxTextureCoords);
-   add_builtin_constant(instructions, state, "gl_MaxVertexAttribs",
+   add_builtin_constant(instructions, symtab, "gl_MaxVertexAttribs",
 			state->Const.MaxVertexAttribs);
-   add_builtin_constant(instructions, state, "gl_MaxVertexUniformComponents",
+   add_builtin_constant(instructions, symtab, "gl_MaxVertexUniformComponents",
 			state->Const.MaxVertexUniformComponents);
-   add_builtin_constant(instructions, state, "gl_MaxVaryingFloats",
+   add_builtin_constant(instructions, symtab, "gl_MaxVaryingFloats",
 			state->Const.MaxVaryingFloats);
-   add_builtin_constant(instructions, state, "gl_MaxVertexTextureImageUnits",
+   add_builtin_constant(instructions, symtab, "gl_MaxVertexTextureImageUnits",
 			state->Const.MaxVertexTextureImageUnits);
-   add_builtin_constant(instructions, state, "gl_MaxCombinedTextureImageUnits",
+   add_builtin_constant(instructions, symtab, "gl_MaxCombinedTextureImageUnits",
 			state->Const.MaxCombinedTextureImageUnits);
-   add_builtin_constant(instructions, state, "gl_MaxTextureImageUnits",
+   add_builtin_constant(instructions, symtab, "gl_MaxTextureImageUnits",
 			state->Const.MaxTextureImageUnits);
-   add_builtin_constant(instructions, state, "gl_MaxFragmentUniformComponents",
+   add_builtin_constant(instructions, symtab, "gl_MaxFragmentUniformComponents",
 			state->Const.MaxFragmentUniformComponents);
 
    const glsl_type *const mat4_array_type =
       glsl_type::get_array_instance(glsl_type::mat4_type,
 				    state->Const.MaxTextureCoords);
 
-   add_uniform(instructions, state, "gl_TextureMatrix", mat4_array_type);
-   add_uniform(instructions, state, "gl_TextureMatrixInverse", mat4_array_type);
-   add_uniform(instructions, state, "gl_TextureMatrixTranspose", mat4_array_type);
-   add_uniform(instructions, state, "gl_TextureMatrixInverseTranspose", mat4_array_type);
+   add_uniform(instructions, symtab, "gl_TextureMatrix", mat4_array_type);
+   add_uniform(instructions, symtab, "gl_TextureMatrixInverse", mat4_array_type);
+   add_uniform(instructions, symtab, "gl_TextureMatrixTranspose", mat4_array_type);
+   add_uniform(instructions, symtab, "gl_TextureMatrixInverseTranspose", mat4_array_type);
 
-   add_uniform(instructions, state, "gl_DepthRange",
-		state->symbols->get_type("gl_DepthRangeParameters"));
+   add_uniform(instructions, symtab, "gl_DepthRange",
+		symtab->get_type("gl_DepthRangeParameters"));
 
-   add_uniform(instructions, state, "gl_ClipPlane",
+   add_uniform(instructions, symtab, "gl_ClipPlane",
 	       glsl_type::get_array_instance(glsl_type::vec4_type,
 					     state->Const.MaxClipPlanes));
-   add_uniform(instructions, state, "gl_Point",
-	       state->symbols->get_type("gl_PointParameters"));
+   add_uniform(instructions, symtab, "gl_Point",
+	       symtab->get_type("gl_PointParameters"));
 
    const glsl_type *const material_parameters_type =
-      state->symbols->get_type("gl_MaterialParameters");
-   add_uniform(instructions, state, "gl_FrontMaterial", material_parameters_type);
-   add_uniform(instructions, state, "gl_BackMaterial", material_parameters_type);
+      symtab->get_type("gl_MaterialParameters");
+   add_uniform(instructions, symtab, "gl_FrontMaterial", material_parameters_type);
+   add_uniform(instructions, symtab, "gl_BackMaterial", material_parameters_type);
 
    const glsl_type *const light_source_array_type =
-      glsl_type::get_array_instance(state->symbols->get_type("gl_LightSourceParameters"), state->Const.MaxLights);
+      glsl_type::get_array_instance(symtab->get_type("gl_LightSourceParameters"), state->Const.MaxLights);
 
-   add_uniform(instructions, state, "gl_LightSource", light_source_array_type);
+   add_uniform(instructions, symtab, "gl_LightSource", light_source_array_type);
 
    const glsl_type *const light_model_products_type =
-      state->symbols->get_type("gl_LightModelProducts");
-   add_uniform(instructions, state, "gl_FrontLightModelProduct",
+      symtab->get_type("gl_LightModelProducts");
+   add_uniform(instructions, symtab, "gl_FrontLightModelProduct",
 	       light_model_products_type);
-   add_uniform(instructions, state, "gl_BackLightModelProduct",
+   add_uniform(instructions, symtab, "gl_BackLightModelProduct",
 	       light_model_products_type);
 
    const glsl_type *const light_products_type =
-      glsl_type::get_array_instance(state->symbols->get_type("gl_LightProducts"),
+      glsl_type::get_array_instance(symtab->get_type("gl_LightProducts"),
 				    state->Const.MaxLights);
-   add_uniform(instructions, state, "gl_FrontLightProduct", light_products_type);
-   add_uniform(instructions, state, "gl_BackLightProduct", light_products_type);
+   add_uniform(instructions, symtab, "gl_FrontLightProduct", light_products_type);
+   add_uniform(instructions, symtab, "gl_BackLightProduct", light_products_type);
 
-   add_uniform(instructions, state, "gl_TextureEnvColor",
+   add_uniform(instructions, symtab, "gl_TextureEnvColor",
 	       glsl_type::get_array_instance(glsl_type::vec4_type,
 					     state->Const.MaxTextureUnits));
 
    const glsl_type *const texcoords_vec4 =
       glsl_type::get_array_instance(glsl_type::vec4_type,
 				    state->Const.MaxTextureCoords);
-   add_uniform(instructions, state, "gl_EyePlaneS", texcoords_vec4);
-   add_uniform(instructions, state, "gl_EyePlaneT", texcoords_vec4);
-   add_uniform(instructions, state, "gl_EyePlaneR", texcoords_vec4);
-   add_uniform(instructions, state, "gl_EyePlaneQ", texcoords_vec4);
-   add_uniform(instructions, state, "gl_ObjectPlaneS", texcoords_vec4);
-   add_uniform(instructions, state, "gl_ObjectPlaneT", texcoords_vec4);
-   add_uniform(instructions, state, "gl_ObjectPlaneR", texcoords_vec4);
-   add_uniform(instructions, state, "gl_ObjectPlaneQ", texcoords_vec4);
-
-   add_uniform(instructions, state, "gl_Fog",
-	       state->symbols->get_type("gl_FogParameters"));
+   add_uniform(instructions, symtab, "gl_EyePlaneS", texcoords_vec4);
+   add_uniform(instructions, symtab, "gl_EyePlaneT", texcoords_vec4);
+   add_uniform(instructions, symtab, "gl_EyePlaneR", texcoords_vec4);
+   add_uniform(instructions, symtab, "gl_EyePlaneQ", texcoords_vec4);
+   add_uniform(instructions, symtab, "gl_ObjectPlaneS", texcoords_vec4);
+   add_uniform(instructions, symtab, "gl_ObjectPlaneT", texcoords_vec4);
+   add_uniform(instructions, symtab, "gl_ObjectPlaneR", texcoords_vec4);
+   add_uniform(instructions, symtab, "gl_ObjectPlaneQ", texcoords_vec4);
+
+   add_uniform(instructions, symtab, "gl_Fog",
+	       symtab->get_type("gl_FogParameters"));
 }
 
 /* This function should only be called for ES, not desktop GL. */
@@ -232,8 +233,8 @@ generate_100ES_vs_variables(exec_list *instructions,
 			  struct _mesa_glsl_parse_state *state)
 {
    for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) {
-      add_builtin_variable(& builtin_core_vs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_core_vs_variables[i]);
    }
 
    generate_100ES_uniforms(instructions, state);
@@ -248,15 +249,15 @@ generate_110_vs_variables(exec_list *instructions,
 			  struct _mesa_glsl_parse_state *state)
 {
    for (unsigned i = 0; i < Elements(builtin_core_vs_variables); i++) {
-      add_builtin_variable(& builtin_core_vs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_core_vs_variables[i]);
    }
 
    for (unsigned i = 0
 	   ; i < Elements(builtin_110_deprecated_vs_variables)
 	   ; i++) {
-      add_builtin_variable(& builtin_110_deprecated_vs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_110_deprecated_vs_variables[i]);
    }
    generate_110_uniforms(instructions, state);
 
@@ -271,8 +272,8 @@ generate_110_vs_variables(exec_list *instructions,
    const glsl_type *const vec4_array_type =
       glsl_type::get_array_instance(glsl_type::vec4_type, 0);
 
-   add_variable("gl_TexCoord", ir_var_out, VERT_RESULT_TEX0, vec4_array_type,
-		instructions, state->symbols);
+   add_variable(instructions, state->symbols,
+		"gl_TexCoord", vec4_array_type, ir_var_out, VERT_RESULT_TEX0);
 
    generate_ARB_draw_buffers_variables(instructions, state, false,
 				       vertex_shader);
@@ -297,8 +298,8 @@ generate_130_vs_variables(exec_list *instructions,
    generate_120_vs_variables(instructions, state);
 
    for (unsigned i = 0; i < Elements(builtin_130_vs_variables); i++) {
-      add_builtin_variable(& builtin_130_vs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_130_vs_variables[i]);
    }
 
    const glsl_type *const clip_distance_array_type =
@@ -306,8 +307,8 @@ generate_130_vs_variables(exec_list *instructions,
 				    state->Const.MaxClipPlanes);
 
    /* FINISHME: gl_ClipDistance needs a real location assigned. */
-   add_variable("gl_ClipDistance", ir_var_out, -1, clip_distance_array_type,
-		instructions, state->symbols);
+   add_variable(instructions, state->symbols,
+		"gl_ClipDistance", clip_distance_array_type, ir_var_out, -1);
 
 }
 
@@ -344,13 +345,13 @@ generate_100ES_fs_variables(exec_list *instructions,
 			  struct _mesa_glsl_parse_state *state)
 {
    for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) {
-      add_builtin_variable(& builtin_core_fs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_core_fs_variables[i]);
    }
 
    for (unsigned i = 0; i < Elements(builtin_100ES_fs_variables); i++) {
-      add_builtin_variable(& builtin_100ES_fs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_100ES_fs_variables[i]);
    }
 
    generate_100ES_uniforms(instructions, state);
@@ -364,20 +365,20 @@ generate_110_fs_variables(exec_list *instructions,
 			  struct _mesa_glsl_parse_state *state)
 {
    for (unsigned i = 0; i < Elements(builtin_core_fs_variables); i++) {
-      add_builtin_variable(& builtin_core_fs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_core_fs_variables[i]);
    }
 
    for (unsigned i = 0; i < Elements(builtin_110_fs_variables); i++) {
-      add_builtin_variable(& builtin_110_fs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_110_fs_variables[i]);
    }
 
    for (unsigned i = 0
 	   ; i < Elements(builtin_110_deprecated_fs_variables)
 	   ; i++) {
-      add_builtin_variable(& builtin_110_deprecated_fs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_110_deprecated_fs_variables[i]);
    }
    generate_110_uniforms(instructions, state);
 
@@ -392,8 +393,8 @@ generate_110_fs_variables(exec_list *instructions,
    const glsl_type *const vec4_array_type =
       glsl_type::get_array_instance(glsl_type::vec4_type, 0);
 
-   add_variable("gl_TexCoord", ir_var_in, FRAG_ATTRIB_TEX0, vec4_array_type,
-		instructions, state->symbols);
+   add_variable(instructions, state->symbols,
+		"gl_TexCoord", vec4_array_type, ir_var_in, FRAG_ATTRIB_TEX0);
 
    generate_ARB_draw_buffers_variables(instructions, state, false,
 				       fragment_shader);
@@ -408,8 +409,8 @@ generate_ARB_draw_buffers_variables(exec_list *instructions,
    /* gl_MaxDrawBuffers is available in all shader stages.
     */
    ir_variable *const mdb =
-      add_variable("gl_MaxDrawBuffers", ir_var_auto, -1,
-		   glsl_type::int_type, instructions, state->symbols);
+      add_variable(instructions, state->symbols,
+		   "gl_MaxDrawBuffers", glsl_type::int_type, ir_var_auto, -1);
 
    if (warn)
       mdb->warn_extension = "GL_ARB_draw_buffers";
@@ -426,8 +427,9 @@ generate_ARB_draw_buffers_variables(exec_list *instructions,
 				       state->Const.MaxDrawBuffers);
 
       ir_variable *const fd =
-	 add_variable("gl_FragData", ir_var_out, FRAG_RESULT_DATA0,
-		      vec4_array_type, instructions, state->symbols);
+	 add_variable(instructions, state->symbols,
+		      "gl_FragData", vec4_array_type,
+		      ir_var_out, FRAG_RESULT_DATA0);
 
       if (warn)
 	 fd->warn_extension = "GL_ARB_draw_buffers";
@@ -445,9 +447,9 @@ generate_ARB_draw_instanced_variables(exec_list *instructions,
     */
    if (target == vertex_shader) {
       ir_variable *const inst =
-         add_variable("gl_InstanceIDARB", ir_var_system_value,
-                      SYSTEM_VALUE_INSTANCE_ID,
-                      glsl_type::int_type, instructions, state->symbols);
+         add_variable(instructions, state->symbols,
+		      "gl_InstanceIDARB", glsl_type::int_type,
+		      ir_var_system_value, SYSTEM_VALUE_INSTANCE_ID);
 
       if (warn)
          inst->warn_extension = "GL_ARB_draw_instanced";
@@ -463,8 +465,9 @@ generate_ARB_shader_stencil_export_variables(exec_list *instructions,
    /* gl_FragStencilRefARB is only available in the fragment shader.
     */
    ir_variable *const fd =
-      add_variable("gl_FragStencilRefARB", ir_var_out, FRAG_RESULT_STENCIL,
-		   glsl_type::int_type, instructions, state->symbols);
+      add_variable(instructions, state->symbols,
+		   "gl_FragStencilRefARB", glsl_type::int_type,
+		   ir_var_out, FRAG_RESULT_STENCIL);
 
    if (warn)
       fd->warn_extension = "GL_ARB_shader_stencil_export";
@@ -479,8 +482,8 @@ generate_120_fs_variables(exec_list *instructions,
    for (unsigned i = 0
 	   ; i < Elements(builtin_120_fs_variables)
 	   ; i++) {
-      add_builtin_variable(& builtin_120_fs_variables[i],
-			   instructions, state->symbols);
+      add_builtin_variable(instructions, state->symbols,
+			   & builtin_120_fs_variables[i]);
    }
 }
 
@@ -495,8 +498,8 @@ generate_130_fs_variables(exec_list *instructions,
 				    state->Const.MaxClipPlanes);
 
    /* FINISHME: gl_ClipDistance needs a real location assigned. */
-   add_variable("gl_ClipDistance", ir_var_in, -1, clip_distance_array_type,
-		instructions, state->symbols);
+   add_variable(instructions, state->symbols,
+		"gl_ClipDistance", clip_distance_array_type, ir_var_in, -1);
 }
 
 static void
-- 
cgit v1.2.3