Mesa (glsl2): glsl2: Add and use new variable mode ir_var_temporary

Ian Romanick idr at kemper.freedesktop.org
Wed Jul 21 00:52:47 UTC 2010


Module: Mesa
Branch: glsl2
Commit: 7e2aa91507a5883e33473e0a94215ee3985baad1
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=7e2aa91507a5883e33473e0a94215ee3985baad1

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Mon Jul 19 17:12:42 2010 -0700

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'.

---

 src/glsl/ast_function.cpp                |   21 ++++++++----
 src/glsl/ast_to_hir.cpp                  |   26 +++++++++------
 src/glsl/glsl_types.cpp                  |    7 ++--
 src/glsl/ir.cpp                          |    6 ++-
 src/glsl/ir.h                            |    5 ++-
 src/glsl/ir_clone.cpp                    |    4 +-
 src/glsl/ir_expression_flattening.cpp    |    2 +-
 src/glsl/ir_function.cpp                 |    1 +
 src/glsl/ir_function_inlining.cpp        |    3 +-
 src/glsl/ir_if_return.cpp                |    3 +-
 src/glsl/ir_if_to_cond_assign.cpp        |    3 +-
 src/glsl/ir_mat_op_to_vec.cpp            |    3 +-
 src/glsl/ir_mod_to_fract.cpp             |    3 +-
 src/glsl/ir_reader.cpp                   |    3 +-
 src/glsl/ir_variable.cpp                 |    3 +-
 src/glsl/ir_vec_index_to_cond_assign.cpp |   12 +++++--
 src/glsl/linker.cpp                      |   50 ++++++++++++++++++++++++++---
 src/mesa/shader/ir_to_mesa.cpp           |    1 +
 18 files changed, 109 insertions(+), 47 deletions(-)

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 643eb22..14c36af 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -115,7 +115,8 @@ process_call(exec_list *instructions, ir_function *f,
 
 	 var = new(ctx) ir_variable(sig->return_type,
 				    talloc_asprintf(ctx, "%s_retval",
-						    sig->function_name()));
+						    sig->function_name()),
+				    ir_var_temporary);
 	 instructions->push_tail(var);
 
 	 deref = new(ctx) ir_dereference_variable(var);
@@ -509,7 +510,8 @@ emit_inline_vector_constructor(const glsl_type *type,
    assert(!parameters->is_empty());
 
    ir_variable *var = new(ctx) ir_variable(type,
-					   talloc_strdup(ctx, "vec_ctor"));
+					   talloc_strdup(ctx, "vec_ctor"),
+					   ir_var_temporary);
    instructions->push_tail(var);
 
    /* There are two kinds of vector constructors.
@@ -621,7 +623,8 @@ emit_inline_matrix_constructor(const glsl_type *type,
    assert(!parameters->is_empty());
 
    ir_variable *var = new(ctx) ir_variable(type,
-					   talloc_strdup(ctx, "mat_ctor"));
+					   talloc_strdup(ctx, "mat_ctor"),
+					   ir_var_temporary);
    instructions->push_tail(var);
 
    /* There are three kinds of matrix constructors.
@@ -645,7 +648,8 @@ emit_inline_matrix_constructor(const glsl_type *type,
        */
       ir_variable *rhs_var =
 	 new(ctx) ir_variable(glsl_type::vec4_type,
-			      talloc_strdup(ctx, "mat_ctor_vec"));
+			      talloc_strdup(ctx, "mat_ctor_vec"),
+			      ir_var_temporary);
       instructions->push_tail(rhs_var);
 
       ir_constant_data zero;
@@ -759,7 +763,8 @@ emit_inline_matrix_constructor(const glsl_type *type,
        */
       ir_variable *const rhs_var =
 	 new(ctx) ir_variable(first_param->type,
-			      talloc_strdup(ctx, "mat_ctor_mat"));
+			      talloc_strdup(ctx, "mat_ctor_mat"),
+			      ir_var_temporary);
       instructions->push_tail(rhs_var);
 
       ir_dereference *const rhs_var_ref =
@@ -825,7 +830,8 @@ emit_inline_matrix_constructor(const glsl_type *type,
 	  */
 	 ir_variable *rhs_var =
 	    new(ctx) ir_variable(rhs->type,
-				 talloc_strdup(ctx, "mat_ctor_vec"));
+				 talloc_strdup(ctx, "mat_ctor_vec"),
+				 ir_var_temporary);
 	 instructions->push_tail(rhs_var);
 
 	 ir_dereference *rhs_var_ref =
@@ -1036,7 +1042,8 @@ ast_function_expression::hir(exec_list *instructions,
 	       continue;
 
 	    /* Create a temporary containing the matrix. */
-	    ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp");
+	    ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp",
+						    ir_var_temporary);
 	    instructions->push_tail(var);
 	    instructions->push_tail(new(ctx) ir_assignment(new(ctx)
 	       ir_dereference_variable(var), matrix, NULL));
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index f20c7ea..c68e136 100644
--- a/src/glsl/ast_to_hir.cpp
+++ b/src/glsl/ast_to_hir.cpp
@@ -527,7 +527,8 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
     * temporary and return a deref of that temporary.  If the rvalue
     * ends up not being used, the temp will get copy-propagated out.
     */
-   ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp");
+   ir_variable *var = new(ctx) ir_variable(rhs->type, "assignment_tmp",
+					   ir_var_temporary);
    ir_dereference_variable *deref_var = new(ctx) ir_dereference_variable(var);
    instructions->push_tail(var);
    instructions->push_tail(new(ctx) ir_assignment(deref_var,
@@ -549,7 +550,8 @@ get_lvalue_copy(exec_list *instructions, ir_rvalue *lvalue)
    ir_variable *var;
 
    /* FINISHME: Give unique names to the temporaries. */
-   var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp");
+   var = new(ctx) ir_variable(lvalue->type, "_post_incdec_tmp",
+			      ir_var_temporary);
    instructions->push_tail(var);
    var->mode = ir_var_auto;
 
@@ -806,7 +808,8 @@ ast_expression::hir(exec_list *instructions,
 	 type = glsl_type::bool_type;
       } else {
 	 ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
-						       "and_tmp");
+						       "and_tmp",
+						       ir_var_temporary);
 	 instructions->push_tail(tmp);
 
 	 ir_if *const stmt = new(ctx) ir_if(op[0]);
@@ -870,7 +873,8 @@ ast_expression::hir(exec_list *instructions,
 	 type = glsl_type::bool_type;
       } else {
 	 ir_variable *const tmp = new(ctx) ir_variable(glsl_type::bool_type,
-						       "or_tmp");
+						       "or_tmp",
+						       ir_var_temporary);
 	 instructions->push_tail(tmp);
 
 	 ir_if *const stmt = new(ctx) ir_if(op[0]);
@@ -1049,7 +1053,8 @@ ast_expression::hir(exec_list *instructions,
 	  && (cond_val != NULL) && (then_val != NULL) && (else_val != NULL)) {
 	 result = (cond_val->value.b[0]) ? then_val : else_val;
       } else {
-	 ir_variable *const tmp = new(ctx) ir_variable(type, "conditional_tmp");
+	 ir_variable *const tmp =
+	    new(ctx) ir_variable(type, "conditional_tmp", ir_var_temporary);
 	 instructions->push_tail(tmp);
 
 	 ir_if *const stmt = new(ctx) ir_if(op[0]);
@@ -1474,6 +1479,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
+   /* If there is no qualifier that changes the mode of the variable, leave
+    * the setting alone.
+    */
    if (qual->in && qual->out)
       var->mode = ir_var_inout;
    else if (qual->attribute || qual->in
@@ -1483,8 +1491,6 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       var->mode = ir_var_out;
    else if (qual->uniform)
       var->mode = ir_var_uniform;
-   else
-      var->mode = ir_var_auto;
 
    if (qual->uniform)
       var->shader_in = true;
@@ -1633,7 +1639,7 @@ ast_declarator_list::hir(exec_list *instructions,
 	 var_type = decl_type;
       }
 
-      var = new(ctx) ir_variable(var_type, decl->identifier);
+      var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
 
       /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
        *
@@ -1993,7 +1999,7 @@ ast_parameter_declarator::hir(exec_list *instructions,
    }
 
    is_void = false;
-   ir_variable *var = new(ctx) ir_variable(type, this->identifier);
+   ir_variable *var = new(ctx) ir_variable(type, this->identifier, ir_var_in);
 
    /* FINISHME: Handle array declarations.  Note that this requires
     * FINISHME: complete handling of constant expressions.
@@ -2003,8 +2009,6 @@ ast_parameter_declarator::hir(exec_list *instructions,
     * for function parameters the default mode is 'in'.
     */
    apply_type_qualifier_to_variable(& this->type->qualifier, var, state, & loc);
-   if (var->mode == ir_var_auto)
-      var->mode = ir_var_in;
 
    instructions->push_tail(var);
 
diff --git a/src/glsl/glsl_types.cpp b/src/glsl/glsl_types.cpp
index 77c591e..5cb327c 100644
--- a/src/glsl/glsl_types.cpp
+++ b/src/glsl/glsl_types.cpp
@@ -251,10 +251,9 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const
       snprintf(param_name, 10, "p%08X", i);
 
       ir_variable *var = (this->base_type == GLSL_TYPE_ARRAY)
-	 ? new(ctx) ir_variable(fields.array, param_name)
-	 : new(ctx) ir_variable(fields.structure[i].type, param_name);
+	 ? new(ctx) ir_variable(fields.array, param_name, ir_var_in)
+	 : new(ctx) ir_variable(fields.structure[i].type, param_name, ir_var_in);
 
-      var->mode = ir_var_in;
       declarations[i] = var;
       sig->parameters.push_tail(var);
    }
@@ -264,7 +263,7 @@ glsl_type::generate_constructor(glsl_symbol_table *symtab) const
     * the same type as the constructor.  After initializing __retval,
     * __retval is returned.
     */
-   ir_variable *retval = new(ctx) ir_variable(this, "__retval");
+   ir_variable *retval = new(ctx) ir_variable(this, "__retval", ir_var_auto);
    sig->body.push_tail(retval);
 
    for (unsigned i = 0; i < length; i++) {
diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
index ba8ee7b..146ff17 100644
--- a/src/glsl/ir.cpp
+++ b/src/glsl/ir.cpp
@@ -748,10 +748,12 @@ ir_swizzle::variable_referenced()
    return this->val->variable_referenced();
 }
 
-ir_variable::ir_variable(const struct glsl_type *type, const char *name)
+
+ir_variable::ir_variable(const struct glsl_type *type, const char *name,
+			 ir_variable_mode mode)
    : max_array_access(0), read_only(false), centroid(false), invariant(false),
      shader_in(false), shader_out(false),
-     mode(ir_var_auto), interpolation(ir_var_smooth), array_lvalue(false)
+     mode(mode), interpolation(ir_var_smooth), array_lvalue(false)
 {
    this->ir_type = ir_type_variable;
    this->type = type;
diff --git a/src/glsl/ir.h b/src/glsl/ir.h
index 3be0962..9fd9850 100644
--- a/src/glsl/ir.h
+++ b/src/glsl/ir.h
@@ -162,7 +162,8 @@ enum ir_variable_mode {
    ir_var_uniform,
    ir_var_in,
    ir_var_out,
-   ir_var_inout
+   ir_var_inout,
+   ir_var_temporary	/**< Temporary variable generated during compilation. */
 };
 
 enum ir_variable_interpolation {
@@ -174,7 +175,7 @@ enum ir_variable_interpolation {
 
 class ir_variable : public ir_instruction {
 public:
-   ir_variable(const struct glsl_type *, const char *);
+   ir_variable(const struct glsl_type *, const char *, ir_variable_mode);
 
    virtual ir_variable *clone(struct hash_table *ht) const;
 
diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp
index 91d6977..f7e8794 100644
--- a/src/glsl/ir_clone.cpp
+++ b/src/glsl/ir_clone.cpp
@@ -39,7 +39,8 @@ ir_variable *
 ir_variable::clone(struct hash_table *ht) const
 {
    void *ctx = talloc_parent(this);
-   ir_variable *var = new(ctx) ir_variable(type, name);
+   ir_variable *var = new(ctx) ir_variable(this->type, this->name,
+					   (ir_variable_mode) this->mode);
 
    var->max_array_access = this->max_array_access;
    var->read_only = this->read_only;
@@ -47,7 +48,6 @@ ir_variable::clone(struct hash_table *ht) const
    var->invariant = this->invariant;
    var->shader_in = this->shader_in;
    var->shader_out = this->shader_out;
-   var->mode = this->mode;
    var->interpolation = this->interpolation;
    var->array_lvalue = this->array_lvalue;
    var->location = this->location;
diff --git a/src/glsl/ir_expression_flattening.cpp b/src/glsl/ir_expression_flattening.cpp
index f186593..6dbebc6 100644
--- a/src/glsl/ir_expression_flattening.cpp
+++ b/src/glsl/ir_expression_flattening.cpp
@@ -89,7 +89,7 @@ ir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir)
    if (!this->predicate(ir))
       return ir;
 
-   var = new(ctx) ir_variable(ir->type, "flattening_tmp");
+   var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary);
    base_ir->insert_before(var);
 
    assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
diff --git a/src/glsl/ir_function.cpp b/src/glsl/ir_function.cpp
index e85b18c..28a5c39 100644
--- a/src/glsl/ir_function.cpp
+++ b/src/glsl/ir_function.cpp
@@ -116,6 +116,7 @@ parameter_lists_match(const exec_list *list_a, const exec_list *list_b)
       switch ((enum ir_variable_mode)(param->mode)) {
       case ir_var_auto:
       case ir_var_uniform:
+      case ir_var_temporary:
 	 /* These are all error conditions.  It is invalid for a parameter to
 	  * a function to be declared as auto (not in, out, or inout) or
 	  * as uniform.
diff --git a/src/glsl/ir_function_inlining.cpp b/src/glsl/ir_function_inlining.cpp
index a3f7089..05dd83f 100644
--- a/src/glsl/ir_function_inlining.cpp
+++ b/src/glsl/ir_function_inlining.cpp
@@ -122,7 +122,8 @@ ir_call::generate_inline(ir_instruction *next_ir)
 
    /* Generate storage for the return value. */
    if (this->callee->return_type) {
-      retval = new(ctx) ir_variable(this->callee->return_type, "__retval");
+      retval = new(ctx) ir_variable(this->callee->return_type, "__retval",
+				    ir_var_auto);
       next_ir->insert_before(retval);
    }
 
diff --git a/src/glsl/ir_if_return.cpp b/src/glsl/ir_if_return.cpp
index f68dcfb..a9af716 100644
--- a/src/glsl/ir_if_return.cpp
+++ b/src/glsl/ir_if_return.cpp
@@ -102,7 +102,8 @@ ir_if_return_visitor::visit_enter(ir_if *ir)
    } else {
       ir_assignment *assign;
       ir_variable *new_var = new(ir) ir_variable(then_return->value->type,
-					     "if_return_tmp");
+						 "if_return_tmp",
+						 ir_var_temporary);
       ir->insert_before(new_var);
 
       assign = new(ir) ir_assignment(new(ir) ir_dereference_variable(new_var),
diff --git a/src/glsl/ir_if_to_cond_assign.cpp b/src/glsl/ir_if_to_cond_assign.cpp
index 274874b..0b87413 100644
--- a/src/glsl/ir_if_to_cond_assign.cpp
+++ b/src/glsl/ir_if_to_cond_assign.cpp
@@ -145,7 +145,8 @@ ir_if_to_cond_assign_visitor::visit_leave(ir_if *ir)
     * simpler.
     */
    cond_var = new(mem_ctx) ir_variable(glsl_type::bool_type,
-				       "if_to_cond_assign_condition");
+				       "if_to_cond_assign_condition",
+				       ir_var_temporary);
    ir->insert_before(cond_var);
 
    deref = new(mem_ctx) ir_dereference_variable(cond_var);
diff --git a/src/glsl/ir_mat_op_to_vec.cpp b/src/glsl/ir_mat_op_to_vec.cpp
index 7bdb905..742fc2a 100644
--- a/src/glsl/ir_mat_op_to_vec.cpp
+++ b/src/glsl/ir_mat_op_to_vec.cpp
@@ -298,7 +298,8 @@ ir_mat_op_to_vec_visitor::visit_leave(ir_assignment *assign)
       ir_assignment *assign;
 
       op_var[i] = new(base_ir) ir_variable(expr->operands[i]->type,
-					   "mat_op_to_vec");
+					   "mat_op_to_vec",
+					   ir_var_temporary);
       base_ir->insert_before(op_var[i]);
 
       lhs_deref = new(base_ir) ir_dereference_variable(op_var[i]);
diff --git a/src/glsl/ir_mod_to_fract.cpp b/src/glsl/ir_mod_to_fract.cpp
index ec1e650..71c9472 100644
--- a/src/glsl/ir_mod_to_fract.cpp
+++ b/src/glsl/ir_mod_to_fract.cpp
@@ -60,7 +60,8 @@ ir_mod_to_fract_visitor::visit_leave(ir_expression *ir)
    if (ir->operation != ir_binop_mod)
       return visit_continue;
 
-   ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b");
+   ir_variable *temp = new(ir) ir_variable(ir->operands[1]->type, "mod_b",
+					   ir_var_temporary);
    this->base_ir->insert_before(temp);
 
    ir_assignment *assign;
diff --git a/src/glsl/ir_reader.cpp b/src/glsl/ir_reader.cpp
index a1e5a7a..ed68496 100644
--- a/src/glsl/ir_reader.cpp
+++ b/src/glsl/ir_reader.cpp
@@ -401,7 +401,8 @@ read_declaration(_mesa_glsl_parse_state *st, s_list *list)
       return NULL;
    }
 
-   ir_variable *var = new(ctx) ir_variable(type, var_name->value());
+   ir_variable *var = new(ctx) ir_variable(type, var_name->value(),
+					   ir_var_auto);
 
    foreach_iter(exec_list_iterator, it, quals->subexpressions) {
       s_symbol *qualifier = SX_AS_SYMBOL(it.get());
diff --git a/src/glsl/ir_variable.cpp b/src/glsl/ir_variable.cpp
index 4593c18..700c5de 100644
--- a/src/glsl/ir_variable.cpp
+++ b/src/glsl/ir_variable.cpp
@@ -39,9 +39,8 @@ add_variable(const char *name, enum ir_variable_mode mode, int slot,
 	     const glsl_type *type, exec_list *instructions,
 		     glsl_symbol_table *symtab)
 {
-   ir_variable *var = new(symtab) ir_variable(type, name);
+   ir_variable *var = new(symtab) ir_variable(type, name, mode);
 
-   var->mode = mode;
    switch (var->mode) {
    case ir_var_auto:
       var->read_only = true;
diff --git a/src/glsl/ir_vec_index_to_cond_assign.cpp b/src/glsl/ir_vec_index_to_cond_assign.cpp
index ac42045..7e04389 100644
--- a/src/glsl/ir_vec_index_to_cond_assign.cpp
+++ b/src/glsl/ir_vec_index_to_cond_assign.cpp
@@ -86,14 +86,16 @@ ir_vec_index_to_cond_assign_visitor::convert_vec_index_to_cond_assign(ir_rvalue
 
    /* Store the index to a temporary to avoid reusing its tree. */
    index = new(base_ir) ir_variable(glsl_type::int_type,
-				    "vec_index_tmp_i");
+				    "vec_index_tmp_i",
+				    ir_var_temporary);
    base_ir->insert_before(index);
    deref = new(base_ir) ir_dereference_variable(index);
    assign = new(base_ir) ir_assignment(deref, orig_deref->array_index, NULL);
    base_ir->insert_before(assign);
 
    /* Temporary where we store whichever value we swizzle out. */
-   var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v");
+   var = new(base_ir) ir_variable(ir->type, "vec_index_tmp_v",
+				  ir_var_temporary);
    base_ir->insert_before(var);
 
    /* Generate a conditional move of each vector element to the temp. */
@@ -166,14 +168,16 @@ ir_vec_index_to_cond_assign_visitor::visit_leave(ir_assignment *ir)
    assert(orig_deref->array_index->type->base_type == GLSL_TYPE_INT);
 
    /* Store the index to a temporary to avoid reusing its tree. */
-   index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i");
+   index = new(ir) ir_variable(glsl_type::int_type, "vec_index_tmp_i",
+			       ir_var_temporary);
    ir->insert_before(index);
    deref = new(ir) ir_dereference_variable(index);
    assign = new(ir) ir_assignment(deref, orig_deref->array_index, NULL);
    ir->insert_before(assign);
 
    /* Store the RHS to a temporary to avoid reusing its tree. */
-   var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v");
+   var = new(ir) ir_variable(ir->rhs->type, "vec_index_tmp_v",
+			     ir_var_temporary);
    ir->insert_before(var);
    deref = new(ir) ir_dereference_variable(var);
    assign = new(ir) ir_assignment(deref, ir->rhs, NULL);
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 @@ mode_string(const ir_variable *var)
    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 @@ cross_validate_globals(struct gl_shader_program *prog,
 	 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 @@ populate_symbol_table(gl_shader *sh)
  */
 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 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols,
 
 	    this->symbols->add_variable(copy->name, copy);
 	    this->instructions->push_head(copy);
+	    ir->var = copy;
 	 }
 
 	 return visit_continue;
@@ -509,9 +528,10 @@ remap_variables(ir_instruction *inst, glsl_symbol_table *symbols,
    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 @@ exec_node *
 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;
+
+      ir_variable *var = inst->as_variable();
+      if ((var != NULL) && (var->mode != ir_var_temporary))
 	 continue;
 
-      assert(inst->as_assignment());
+      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 @@ move_non_declarations(exec_list *instructions, exec_node *last,
       last = inst;
    }
 
+   if (make_copies)
+      hash_table_dtor(temps);
+
    return last;
 }
 
diff --git a/src/mesa/shader/ir_to_mesa.cpp b/src/mesa/shader/ir_to_mesa.cpp
index 352b496..7cc469f 100644
--- a/src/mesa/shader/ir_to_mesa.cpp
+++ b/src/mesa/shader/ir_to_mesa.cpp
@@ -1133,6 +1133,7 @@ ir_to_mesa_visitor::visit(ir_dereference_variable *ir)
 
 	 break;
       case ir_var_auto:
+      case ir_var_temporary:
 	 entry = new(mem_ctx) variable_storage(ir->var, PROGRAM_TEMPORARY,
 					       this->next_temp);
 	 this->variables.push_tail(entry);




More information about the mesa-commit mailing list