summaryrefslogtreecommitdiffstats
path: root/src/glsl/ast_function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl/ast_function.cpp')
-rw-r--r--src/glsl/ast_function.cpp75
1 files changed, 46 insertions, 29 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 1e66033348c..6ecf779c935 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -93,13 +93,40 @@ prototype_string(const glsl_type *return_type, const char *name,
static ir_rvalue *
-process_call(exec_list *instructions, ir_function *f,
- YYLTYPE *loc, exec_list *actual_parameters,
- struct _mesa_glsl_parse_state *state)
+match_function_by_name(exec_list *instructions, const char *name,
+ YYLTYPE *loc, exec_list *actual_parameters,
+ struct _mesa_glsl_parse_state *state)
{
void *ctx = state;
+ ir_function *f = state->symbols->get_function(name);
+ ir_function_signature *sig;
+
+ sig = f ? f->matching_signature(actual_parameters) : NULL;
+
+ /* FINISHME: This doesn't handle the case where shader X contains a
+ * FINISHME: matching signature but shader X + N contains an _exact_
+ * FINISHME: matching signature.
+ */
+ if (sig == NULL && (f == NULL || state->es_shader || !f->has_user_signature()) && state->symbols->get_type(name) == NULL && (state->language_version == 110 || state->symbols->get_variable(name) == NULL)) {
+ /* The current shader doesn't contain a matching function or signature.
+ * Before giving up, look for the prototype in the built-in functions.
+ */
+ for (unsigned i = 0; i < state->num_builtins_to_link; i++) {
+ ir_function *builtin;
+ builtin = state->builtins_to_link[i]->symbols->get_function(name);
+ sig = builtin ? builtin->matching_signature(actual_parameters) : NULL;
+ if (sig != NULL) {
+ if (f == NULL) {
+ f = new(ctx) ir_function(name);
+ state->symbols->add_global_function(f);
+ emit_function(state, instructions, f);
+ }
- ir_function_signature *sig = f->matching_signature(actual_parameters);
+ f->add_signature(sig->clone_prototype(f, NULL));
+ break;
+ }
+ }
+ }
if (sig != NULL) {
/* Verify that 'out' and 'inout' actual parameters are lvalues. This
@@ -164,45 +191,35 @@ process_call(exec_list *instructions, ir_function *f,
return NULL;
}
} else {
- char *str = prototype_string(NULL, f->name, actual_parameters);
+ char *str = prototype_string(NULL, name, actual_parameters);
_mesa_glsl_error(loc, state, "no matching function for call to `%s'",
str);
talloc_free(str);
const char *prefix = "candidates are: ";
- foreach_list (node, &f->signatures) {
- ir_function_signature *sig = (ir_function_signature *) node;
- str = prototype_string(sig->return_type, f->name, &sig->parameters);
- _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
- talloc_free(str);
+ for (int i = -1; i < 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;
- prefix = " ";
- }
+ foreach_list (node, &f->signatures) {
+ ir_function_signature *sig = (ir_function_signature *) node;
- return ir_call::get_error_instruction(ctx);
- }
-}
+ str = prototype_string(sig->return_type, f->name, &sig->parameters);
+ _mesa_glsl_error(loc, state, "%s%s\n", prefix, str);
+ talloc_free(str);
+ prefix = " ";
+ }
-static ir_rvalue *
-match_function_by_name(exec_list *instructions, const char *name,
- YYLTYPE *loc, exec_list *actual_parameters,
- struct _mesa_glsl_parse_state *state)
-{
- void *ctx = state;
- ir_function *f = state->symbols->get_function(name);
+ }
- if (f == NULL) {
- _mesa_glsl_error(loc, state, "function `%s' undeclared", name);
return ir_call::get_error_instruction(ctx);
}
-
- /* Once we've determined that the function being called might exist, try
- * to find an overload of the function that matches the parameters.
- */
- return process_call(instructions, f, loc, actual_parameters, state);
}