aboutsummaryrefslogtreecommitdiffstats
path: root/ast_function.cpp
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2010-06-22 14:22:42 -0700
committerIan Romanick <[email protected]>2010-06-23 10:55:25 -0700
commit53e48d3f6344964d99be89340343630dbf4175d1 (patch)
treea3aa6351fa0d9eaa062f538c5340a46170dd2f14 /ast_function.cpp
parent865cf2d1f5e499916d360a246ad85554f3ff5b02 (diff)
Fix multiple usage of an rvalue in constructor component splitting.
Store the thing in a variable and deref it for each swizzle if we have to. Signed-off-by: Ian Romanick <[email protected]>
Diffstat (limited to 'ast_function.cpp')
-rw-r--r--ast_function.cpp26
1 files changed, 23 insertions, 3 deletions
diff --git a/ast_function.cpp b/ast_function.cpp
index 26050977d52..691e6aeba00 100644
--- a/ast_function.cpp
+++ b/ast_function.cpp
@@ -519,6 +519,7 @@ ast_function_expression::hir(exec_list *instructions,
ast_node *ast = exec_node_data(ast_node, n, link);
ir_rvalue *result =
ast->hir(instructions, state)->as_rvalue();
+ ir_variable *result_var = NULL;
/* Attempt to convert the parameter to a constant valued expression.
* After doing so, track whether or not all the parameters to the
@@ -559,6 +560,19 @@ ast_function_expression::hir(exec_list *instructions,
else
nonmatrix_parameters++;
+ /* We can't use the same instruction node in the multiple
+ * swizzle dereferences that happen, so assign it to a
+ * variable and deref that. Plus it saves computation for
+ * complicated expressions and handles
+ * glsl-vs-constructor-call.shader_test.
+ */
+ if (result->type->components() >= 1 && !result->as_constant()) {
+ result_var = new ir_variable(result->type, "constructor_tmp");
+ ir_dereference_variable *lhs;
+
+ lhs = new ir_dereference_variable(result_var);
+ instructions->push_tail(new ir_assignment(lhs, result, NULL));
+ }
/* Process each of the components of the parameter. Dereference
* each component individually, perform any type conversions, and
@@ -568,9 +582,15 @@ ast_function_expression::hir(exec_list *instructions,
if (components_used >= type_components)
break;
- ir_rvalue *const component =
- convert_component(dereference_component(result, i),
- base_type);
+ ir_rvalue *component;
+
+ if (result_var) {
+ ir_dereference *d = new ir_dereference_variable(result_var);
+ component = dereference_component(d, i);
+ } else {
+ component = dereference_component(result, i);
+ }
+ component = convert_component(component, base_type);
/* All cases that could result in component->type being the
* error type should have already been caught above.