summaryrefslogtreecommitdiff
path: root/src/glsl
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-07-19 17:12:42 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-07-20 17:48:24 -0700
commit7e2aa91507a5883e33473e0a94215ee3985baad1 (patch)
tree0e88667d83141c9359eb00b50d6945b4e18c8e72 /src/glsl
parent1124e5a3cbba839ffd968742bfa3295c8de5498c (diff)
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'.
Diffstat (limited to 'src/glsl')
-rw-r--r--src/glsl/ast_function.cpp21
-rw-r--r--src/glsl/ast_to_hir.cpp26
-rw-r--r--src/glsl/glsl_types.cpp7
-rw-r--r--src/glsl/ir.cpp6
-rw-r--r--src/glsl/ir.h5
-rw-r--r--src/glsl/ir_clone.cpp4
-rw-r--r--src/glsl/ir_expression_flattening.cpp2
-rw-r--r--src/glsl/ir_function.cpp1
-rw-r--r--src/glsl/ir_function_inlining.cpp3
-rw-r--r--src/glsl/ir_if_return.cpp3
-rw-r--r--src/glsl/ir_if_to_cond_assign.cpp3
-rw-r--r--src/glsl/ir_mat_op_to_vec.cpp3
-rw-r--r--src/glsl/ir_mod_to_fract.cpp3
-rw-r--r--src/glsl/ir_reader.cpp3
-rw-r--r--src/glsl/ir_variable.cpp3
-rw-r--r--src/glsl/ir_vec_index_to_cond_assign.cpp12
-rw-r--r--src/glsl/linker.cpp50
17 files changed, 108 insertions, 47 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 643eb229a7..14c36af911 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 f20c7ead33..c68e136256 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 77c591ed69..5cb327c89d 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 ba8ee7b9ac..146ff17af3 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 3be096270d..9fd9850391 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 91d6977354..f7e8794728 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 f18659342f..6dbebc6378 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 e85b18ce02..28a5c399f1 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 a3f7089cdc..05dd83f7ff 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 f68dcfb501..a9af7166b9 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 274874bbb7..0b87413941 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 7bdb9057d8..742fc2a295 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 ec1e65092d..71c9472b12 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 a1e5a7ad74..ed68496587 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 4593c18112..700c5de648 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 ac420454e8..7e04389b5f 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 4869dbe1ca..eb4eb9d20e 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;
}