diff options
author | Kenneth Graunke <[email protected]> | 2012-03-28 15:57:50 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2012-04-02 14:15:29 -0700 |
commit | 909e8899671a45bcc865fe303a8cb697a25634aa (patch) | |
tree | 60248635747d7d004cd133c1fa61916776a044a5 /src | |
parent | 0405bd08ca0e01ebc68891ee1ff47d320983f775 (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 <[email protected]>
Reviewed-by: Eric Anholt <[email protected]>
Reviewed-by: Ian Romanick <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/glsl/ast_function.cpp | 82 |
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' |