summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2010-07-20 15:50:48 -0700
committerEric Anholt <eric@anholt.net>2010-07-20 15:59:04 -0700
commit02d3711a21f5766d286b09fbe1eda5d8520d151a (patch)
tree8c6c2edc767bc912a3a0d5984cb7d6a47ab0b533 /src
parentf8946699ecfa5bc6566821fb855072bbdbd716b2 (diff)
glsl2: Always insert function calls into the instruction stream.
If they have a return value, this means putting it into a temporary and making a deref of the temp be the rvalue, since we don't know if the rvalue will be used or not.
Diffstat (limited to 'src')
-rw-r--r--src/glsl/ast_function.cpp25
1 files changed, 24 insertions, 1 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index aaf1e57ae28..643eb229a77 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -104,7 +104,30 @@ process_call(exec_list *instructions, ir_function *f,
formal_iter.next();
}
- return new(ctx) ir_call(sig, actual_parameters);
+ /* Always insert the call in the instruction stream, and return a deref
+ * of its return val if it returns a value, since we don't know if
+ * the rvalue is going to be assigned to anything or not.
+ */
+ ir_call *call = new(ctx) ir_call(sig, actual_parameters);
+ if (!sig->return_type->is_void()) {
+ ir_variable *var;
+ ir_dereference_variable *deref;
+
+ var = new(ctx) ir_variable(sig->return_type,
+ talloc_asprintf(ctx, "%s_retval",
+ sig->function_name()));
+ instructions->push_tail(var);
+
+ deref = new(ctx) ir_dereference_variable(var);
+ ir_assignment *assign = new(ctx) ir_assignment(deref, call, NULL);
+ instructions->push_tail(assign);
+
+ deref = new(ctx) ir_dereference_variable(var);
+ return deref;
+ } else {
+ instructions->push_tail(call);
+ return NULL;
+ }
} else {
/* FINISHME: Log a better error message here. G++ will show the types
* FINISHME: of the actual parameters and the set of candidate