glsl2: Add and use new variable mode ir_var_temporary

This is quite a large patch because breaking it into smaller pieces
would result in the tree being intermitently broken.  The big changes
are:

    * Add the ir_var_temporary variable mode

    * Change the ir_variable constructor to take the mode as a
      parameter and correctly specify the mode for all ir_varables.

    * Change the linker to not cross validate ir_var_temporary
      variables.

    * Change the linker to pull all ir_var_temporary variables from
      global scope into 'main'.
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 4869dbe..eb4eb9d 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -246,6 +246,8 @@
    case ir_var_in:      return "shader input";
    case ir_var_out:     return "shader output";
    case ir_var_inout:   return "shader inout";
+
+   case ir_var_temporary:
    default:
       assert(!"Should not get here.");
       return "invalid variable";
@@ -276,6 +278,12 @@
 	 if (uniforms_only && (var->mode != ir_var_uniform))
 	    continue;
 
+	 /* Don't cross validate temporaries that are at global scope.  These
+	  * will eventually get pulled into the shaders 'main'.
+	  */
+	 if (var->mode == ir_var_temporary)
+	    continue;
+
 	 /* If a global with this name has already been seen, verify that the
 	  * new instance has the same type.  In addition, if the globals have
 	  * initializers, the values of the initializers must be the same.
@@ -480,18 +488,28 @@
  */
 void
 remap_variables(ir_instruction *inst, glsl_symbol_table *symbols,
-		exec_list *instructions)
+		exec_list *instructions, hash_table *temps)
 {
    class remap_visitor : public ir_hierarchical_visitor {
    public:
-      remap_visitor(glsl_symbol_table *symbols, exec_list *instructions)
+      remap_visitor(glsl_symbol_table *symbols, exec_list *instructions,
+		    hash_table *temps)
       {
 	 this->symbols = symbols;
 	 this->instructions = instructions;
+	 this->temps = temps;
       }
 
       virtual ir_visitor_status visit(ir_dereference_variable *ir)
       {
+	 if (ir->var->mode == ir_var_temporary) {
+	    ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var);
+
+	    assert(var != NULL);
+	    ir->var = var;
+	    return visit_continue;
+	 }
+
 	 ir_variable *const existing =
 	    this->symbols->get_variable(ir->var->name);
 	 if (existing != NULL)
@@ -501,6 +519,7 @@
 
 	    this->symbols->add_variable(copy->name, copy);
 	    this->instructions->push_head(copy);
+	    ir->var = copy;
 	 }
 
 	 return visit_continue;
@@ -509,9 +528,10 @@
    private:
       glsl_symbol_table *symbols;
       exec_list *instructions;
+      hash_table *temps;
    };
 
-   remap_visitor v(symbols, instructions);
+   remap_visitor v(symbols, instructions, temps);
 
    inst->accept(&v);
 }
@@ -542,17 +562,32 @@
 move_non_declarations(exec_list *instructions, exec_node *last,
 		      bool make_copies, gl_shader *target)
 {
+   hash_table *temps = NULL;
+
+   if (make_copies)
+      temps = hash_table_ctor(0, hash_table_pointer_hash,
+			      hash_table_pointer_compare);
+
    foreach_list_safe(node, instructions) {
       ir_instruction *inst = (ir_instruction *) node;
 
-      if (inst->as_variable() || inst->as_function())
+      if (inst->as_function())
 	 continue;
 
-      assert(inst->as_assignment());
+      ir_variable *var = inst->as_variable();
+      if ((var != NULL) && (var->mode != ir_var_temporary))
+	 continue;
+
+      assert(inst->as_assignment()
+	     || ((var != NULL) && (var->mode == ir_var_temporary)));
 
       if (make_copies) {
 	 inst = inst->clone(NULL);
-	 remap_variables(inst, target->symbols, target->ir);
+
+	 if (var != NULL)
+	    hash_table_insert(temps, inst, var);
+	 else
+	    remap_variables(inst, target->symbols, target->ir, temps);
       } else {
 	 inst->remove();
       }
@@ -561,6 +596,9 @@
       last = inst;
    }
 
+   if (make_copies)
+      hash_table_dtor(temps);
+
    return last;
 }