summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Graunke <kenneth@whitecape.org>2012-03-28 15:57:50 -0700
committerKenneth Graunke <kenneth@whitecape.org>2012-04-02 14:15:29 -0700
commit909e8899671a45bcc865fe303a8cb697a25634aa (patch)
tree60248635747d7d004cd133c1fa61916776a044a5
parent0405bd08ca0e01ebc68891ee1ff47d320983f775 (diff)
glsl: Split up function matching and call generation a bit more.
We used to have one big function, match_signature_by_name, which found a matching signature, performed out-parameter conversions, and generated the ir_call. As the code for matching against built-in functions became more complicated, I split it internally, creating generate_call(). However, I left the same awkward interface. This patch splits it into three functions: 1. match_signature_by_name() This now takes a name, a list of parameters, the symbol table, and returns an ir_function_signature. Simple and one purpose: matching. 2. no_matching_function_error() Generate the "no matching function" error and list of prototypes. This was complex enough that I felt it deserved its own function. 3. generate_call() Do the out-parameter conversion and generate the ir_call. This could probably use more splitting. The caller now has a more natural workflow: find a matching signature, then either generate an error or a call. Signed-off-by: Kenneth Graunke <kenneth@whitecape.org> Reviewed-by: Eric Anholt <eric@anholt.net> Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
-rw-r--r--src/glsl/ast_function.cpp82
1 files changed, 47 insertions, 35 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 1c2e8613cb2..2ad8fba1f7e 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -275,10 +275,12 @@ generate_call(exec_list *instructions, ir_function_signature *sig,
return deref;
}
-static ir_rvalue *
-match_function_by_name(exec_list *instructions, const char *name,
- YYLTYPE *loc, exec_list *actual_parameters,
- ir_call **call_ir,
+/**
+ * Given a function name and parameter list, find the matching signature.
+ */
+static ir_function_signature *
+match_function_by_name(const char *name,
+ exec_list *actual_parameters,
struct _mesa_glsl_parse_state *state)
{
void *ctx = state;
@@ -350,43 +352,45 @@ done:
}
f->add_signature(sig->clone_prototype(f, NULL));
}
+ }
+ return sig;
+}
- /* Finally, generate a call instruction. */
- return generate_call(instructions, sig, loc, actual_parameters,
- call_ir, state);
- } else {
- char *str = prototype_string(NULL, name, actual_parameters);
-
- _mesa_glsl_error(loc, state, "no matching function for call to `%s'",
- str);
- ralloc_free(str);
-
- const char *prefix = "candidates are: ";
+/**
+ * Raise a "no matching function" error, listing all possible overloads the
+ * compiler considered so developers can figure out what went wrong.
+ */
+static void
+no_matching_function_error(const char *name,
+ YYLTYPE *loc,
+ exec_list *actual_parameters,
+ _mesa_glsl_parse_state *state)
+{
+ char *str = prototype_string(NULL, name, actual_parameters);
+ _mesa_glsl_error(loc, state, "no matching function for call to `%s'", str);
+ ralloc_free(str);
- for (int i = -1; i < (int) state->num_builtins_to_link; i++) {
- glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols
- : state->symbols;
- f = syms->get_function(name);
- if (f == NULL)
- continue;
+ const char *prefix = "candidates are: ";
- foreach_list (node, &f->signatures) {
- ir_function_signature *sig = (ir_function_signature *) node;
+ for (int i = -1; i < (int) state->num_builtins_to_link; i++) {
+ glsl_symbol_table *syms = i >= 0 ? state->builtins_to_link[i]->symbols
+ : state->symbols;
+ ir_function *f = syms->get_function(name);
+ if (f == NULL)
+ continue;
- str = prototype_string(sig->return_type, f->name, &sig->parameters);
- _mesa_glsl_error(loc, state, "%s%s", prefix, str);
- ralloc_free(str);
+ foreach_list (node, &f->signatures) {
+ ir_function_signature *sig = (ir_function_signature *) node;
- prefix = " ";
- }
+ str = prototype_string(sig->return_type, f->name, &sig->parameters);
+ _mesa_glsl_error(loc, state, "%s%s", prefix, str);
+ ralloc_free(str);
+ prefix = " ";
}
-
- return ir_call::get_error_instruction(ctx);
}
}
-
/**
* Perform automatic type conversion of constructor parameters
*
@@ -1447,17 +1451,25 @@ ast_function_expression::hir(exec_list *instructions,
}
} else {
const ast_expression *id = subexpressions[0];
+ const char *func_name = id->primary_expression.identifier;
YYLTYPE loc = id->get_location();
exec_list actual_parameters;
process_parameters(instructions, &actual_parameters, &this->expressions,
state);
+ ir_function_signature *sig =
+ match_function_by_name(func_name, &actual_parameters, state);
+
ir_call *call = NULL;
- ir_rvalue *const value =
- match_function_by_name(instructions,
- id->primary_expression.identifier,
- &loc, &actual_parameters, &call, state);
+ ir_rvalue *value = NULL;
+ if (sig == NULL) {
+ no_matching_function_error(func_name, &loc, &actual_parameters, state);
+ value = ir_call::get_error_instruction(ctx);
+ } else {
+ value = generate_call(instructions, sig, &loc, &actual_parameters,
+ &call, state);
+ }
if (call != NULL) {
/* If a function was found, make sure that none of the 'out' or 'inout'