diff options
author | Eric Anholt <[email protected]> | 2010-06-22 14:22:42 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-06-23 10:55:25 -0700 |
commit | 53e48d3f6344964d99be89340343630dbf4175d1 (patch) | |
tree | a3aa6351fa0d9eaa062f538c5340a46170dd2f14 | |
parent | 865cf2d1f5e499916d360a246ad85554f3ff5b02 (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]>
-rw-r--r-- | ast_function.cpp | 26 |
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. |