On 23 December 2011 14:35, Ian Romanick <span dir="ltr"><<a href="mailto:idr@freedesktop.org" target="_blank">idr@freedesktop.org</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
From: Ian Romanick <<a href="mailto:ian.d.romanick@intel.com" target="_blank">ian.d.romanick@intel.com</a>><br>
<br>
Somethings, like pre-increment operations, were not previously caught.<br>
After the 8.0 release, this code needs some major refactoring and<br>
clean-up. It's a mess. :(<br>
<br>
Signed-off-by: Ian Romanick <<a href="mailto:ian.d.romanick@intel.com" target="_blank">ian.d.romanick@intel.com</a>><br>
Bugzilla: <a href="https://bugs.freedesktop.org/show_bug.cgi?id=42755" target="_blank">https://bugs.freedesktop.org/show_bug.cgi?id=42755</a><br>
---<br>
src/glsl/ast_function.cpp | 57 +++++++++++++++++++++++++++++++++++++++++---<br>
1 files changed, 53 insertions(+), 4 deletions(-)<br>
<br>
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp<br>
index 126b610..4471c76 100644<br>
--- a/src/glsl/ast_function.cpp<br>
+++ b/src/glsl/ast_function.cpp<br>
@@ -96,6 +96,7 @@ prototype_string(const glsl_type *return_type, const char *name,<br>
static ir_rvalue *<br>
generate_call(exec_list *instructions, ir_function_signature *sig,<br>
YYLTYPE *loc, exec_list *actual_parameters,<br>
+ ir_call **call_ir,<br>
struct _mesa_glsl_parse_state *state)<br></blockquote><div><br>Another minor suggestion: The semantics of call_ir are:<br><br>- If generate_call is successful, it is set to the ir_call that is generated.<br>
- If an error occurred, it is unchanged.<br>
<br>This means that in order for the caller to be robust in the case of error conditions, it must remember to set call_ir to NULL before calling this function.<br><br>You're doing that, so there's no bug, but I'd feel better about the situation if we set *call_ir to NULL at the top of generate_call rather than in the caller. That way call_ir would behave like a true out parameter even in the case of error.<br>
<br>As with my other comment, I'm not married to the idea; either way the series is:<br><br>Reviewed-by: Paul Berry <<a href="mailto:stereotype441@gmail.com" target="_blank">stereotype441@gmail.com</a>><br> </div>
<blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
{<br>
void *ctx = state;<br>
@@ -256,10 +257,12 @@ generate_call(exec_list *instructions, ir_function_signature *sig,<br>
deref = new(ctx) ir_dereference_variable(var);<br>
ir_assignment *assign = new(ctx) ir_assignment(deref, call, NULL);<br>
instructions->push_tail(assign);<br>
+ *call_ir = call;<br>
<br>
deref = new(ctx) ir_dereference_variable(var);<br>
} else {<br>
instructions->push_tail(call);<br>
+ *call_ir = call;<br>
deref = NULL;<br>
}<br>
instructions->append_list(&post_call_conversions);<br>
@@ -269,6 +272,7 @@ generate_call(exec_list *instructions, ir_function_signature *sig,<br>
static ir_rvalue *<br>
match_function_by_name(exec_list *instructions, const char *name,<br>
YYLTYPE *loc, exec_list *actual_parameters,<br>
+ ir_call **call_ir,<br>
struct _mesa_glsl_parse_state *state)<br>
{<br>
void *ctx = state;<br>
@@ -342,7 +346,8 @@ done:<br>
}<br>
<br>
/* Finally, generate a call instruction. */<br>
- return generate_call(instructions, sig, loc, actual_parameters, state);<br>
+ return generate_call(instructions, sig, loc, actual_parameters,<br>
+ call_ir, state);<br>
} else {<br>
char *str = prototype_string(NULL, name, actual_parameters);<br>
<br>
@@ -1442,9 +1447,53 @@ ast_function_expression::hir(exec_list *instructions,<br>
process_parameters(instructions, &actual_parameters, &this->expressions,<br>
state);<br>
<br>
- return match_function_by_name(instructions,<br>
- id->primary_expression.identifier, & loc,<br>
- &actual_parameters, state);<br>
+ ir_call *call = NULL;<br>
+ ir_rvalue *const value =<br>
+ match_function_by_name(instructions,<br>
+ id->primary_expression.identifier,<br>
+ &loc, &actual_parameters, &call, state);<br>
+<br>
+ if (call != NULL) {<br>
+ /* If a function was found, make sure that none of the 'out' or 'inout'<br>
+ * parameters violate the extra l-value rules.<br>
+ */<br>
+ ir_function_signature *f = call->get_callee();<br>
+ assert(f != NULL);<br>
+<br>
+ exec_node *formal_node = f->parameters.head;<br>
+<br>
+ foreach_list (actual_node, &this->expressions) {<br>
+ /* Both parameter lists had better be the same length!<br>
+ */<br>
+ assert(!actual_node->is_tail_sentinel());<br>
+<br>
+ const ir_variable *const formal_parameter =<br>
+ (ir_variable *) formal_node;<br>
+ const ast_expression *const actual_parameter =<br>
+ exec_node_data(ast_expression, actual_node, link);<br>
+<br>
+ if ((formal_parameter->mode == ir_var_out<br>
+ || formal_parameter->mode == ir_var_inout)<br>
+ && actual_parameter->non_lvalue_description != NULL) {<br>
+ YYLTYPE loc = actual_parameter->get_location();<br>
+<br>
+ _mesa_glsl_error(&loc, state,<br>
+ "function parameter '%s %s' references a %s",<br>
+ (formal_parameter->mode == ir_var_out)<br>
+ ? "out" : "inout",<br>
+ formal_parameter->name,<br>
+ actual_parameter->non_lvalue_description);<br>
+ return ir_call::get_error_instruction(ctx);<br>
+ }<br>
+<br>
+ /* Only advance the formal_node pointer here because the<br>
+ * foreach_list business already advances actual_node.<br>
+ */<br>
+ formal_node = formal_node->next;<br>
+ }<br>
+ }<br>
+<br>
+ return value;<br>
}<br>
<br>
return ir_call::get_error_instruction(ctx);<br>
<span><font color="#888888">--<br>
1.7.6.4<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org" target="_blank">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br>