summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Graunke <kenneth@whitecape.org>2010-04-28 12:04:23 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-04-28 15:34:52 -0700
commit0d605cb97c9cd2f9a170e3aa15bdf4021a75fc14 (patch)
treec4abee1f1d1c90d18e9c5f7e0916d5769c83b696
parentabd40b15210c17b2a3ba8fcffc868fda203efa01 (diff)
Factor out parameter list matching from ast_function::hir for later reuse.
Unfortunately, we still have two kinds of matching - one, with implicit conversions (for use in calls) and another without them (for finding a prototype to overwrite when processing a function body). This commit does not attempt to coalesce the two.
-rw-r--r--ast_to_hir.cpp79
-rw-r--r--ir.h9
-rw-r--r--ir_function.cpp43
3 files changed, 68 insertions, 63 deletions
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp
index 0e7ab1ab3a..52e372c7e4 100644
--- a/ast_to_hir.cpp
+++ b/ast_to_hir.cpp
@@ -1883,36 +1883,6 @@ ast_parameter_declarator::parameters_to_hir(struct simple_node *ast_parameters,
}
-static bool
-parameter_lists_match(exec_list *list_a, exec_list *list_b)
-{
- exec_list_iterator iter_a = list_a->iterator();
- exec_list_iterator iter_b = list_b->iterator();
-
- while (iter_a.has_next() && iter_b.has_next()) {
- ir_variable *a = (ir_variable *)iter_a.get();
- ir_variable *b = (ir_variable *)iter_b.get();
-
- /* If the types of the parameters do not match, the parameters lists
- * are different.
- */
- if (a->type != b->type)
- return false;
-
- iter_a.next();
- iter_b.next();
- }
-
- /* Unless both lists are exhausted, they differ in length and, by
- * definition, do not match.
- */
- if (iter_a.has_next() != iter_b.has_next())
- return false;
-
- return true;
-}
-
-
ir_rvalue *
ast_function::hir(exec_list *instructions,
struct _mesa_glsl_parse_state *state)
@@ -1943,45 +1913,30 @@ ast_function::hir(exec_list *instructions,
const char *const name = identifier;
f = state->symbols->get_function(name);
if (f != NULL) {
- foreach_iter(exec_list_iterator, iter, *f) {
- sig = (struct ir_function_signature *) iter.get();
-
- /* Compare the parameter list of the function being defined to the
- * existing function. If the parameter lists match, then the return
- * type must also match and the existing function must not have a
- * definition.
- */
- if (parameter_lists_match(& hir_parameters, & sig->parameters)) {
- const char *mismatch = sig->qualifiers_match(&hir_parameters);
- if (mismatch != NULL) {
- YYLTYPE loc = this->get_location();
+ ir_function_signature *sig = f->exact_matching_signature(&hir_parameters);
+ if (sig != NULL) {
+ const char *badvar = sig->qualifiers_match(&hir_parameters);
+ if (badvar != NULL) {
+ YYLTYPE loc = this->get_location();
- _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
- "qualifiers don't match prototype",
- name, mismatch);
- }
+ _mesa_glsl_error(&loc, state, "function `%s' parameter `%s' "
+ "qualifiers don't match prototype", name, badvar);
+ }
- if (sig->return_type != return_type) {
- YYLTYPE loc = this->get_location();
+ if (sig->return_type != return_type) {
+ YYLTYPE loc = this->get_location();
- _mesa_glsl_error(& loc, state,
- "function `%s' return type doesn't match "
- "prototype",
- name);
- }
+ _mesa_glsl_error(&loc, state, "function `%s' return type doesn't "
+ "match prototype", name);
+ }
- if (is_definition && sig->is_defined) {
- YYLTYPE loc = this->get_location();
+ if (is_definition && sig->is_defined) {
+ YYLTYPE loc = this->get_location();
- _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
- sig = NULL;
- break;
- }
+ _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
+ sig = NULL;
}
-
- sig = NULL;
}
-
} else if (state->symbols->name_declared_this_scope(name)) {
/* This function name shadows a non-function use of the same name.
*/
diff --git a/ir.h b/ir.h
index b9ab25b645..118d97ffa3 100644
--- a/ir.h
+++ b/ir.h
@@ -276,11 +276,18 @@ public:
}
/**
- * Find a signature that matches a set of actual parameters.
+ * Find a signature that matches a set of actual parameters, taking implicit
+ * conversions into account.
*/
const ir_function_signature *matching_signature(exec_list *actual_param);
/**
+ * Find a signature that exactly matches a set of actual parameters without
+ * any implicit type conversions.
+ */
+ ir_function_signature *exact_matching_signature(exec_list *actual_ps);
+
+ /**
* Name of the function.
*/
const char *name;
diff --git a/ir_function.cpp b/ir_function.cpp
index a8b73f1e1a..5db93f67fb 100644
--- a/ir_function.cpp
+++ b/ir_function.cpp
@@ -180,3 +180,46 @@ ir_function::matching_signature(exec_list *actual_parameters)
return match;
}
+
+
+static bool
+parameter_lists_match_exact(exec_list *list_a, exec_list *list_b)
+{
+ exec_list_iterator iter_a = list_a->iterator();
+ exec_list_iterator iter_b = list_b->iterator();
+
+ while (iter_a.has_next() && iter_b.has_next()) {
+ ir_variable *a = (ir_variable *)iter_a.get();
+ ir_variable *b = (ir_variable *)iter_b.get();
+
+ /* If the types of the parameters do not match, the parameters lists
+ * are different.
+ */
+ if (a->type != b->type)
+ return false;
+
+ iter_a.next();
+ iter_b.next();
+ }
+
+ /* Unless both lists are exhausted, they differ in length and, by
+ * definition, do not match.
+ */
+ if (iter_a.has_next() != iter_b.has_next())
+ return false;
+
+ return true;
+}
+
+ir_function_signature *
+ir_function::exact_matching_signature(exec_list *actual_parameters)
+{
+ foreach_iter(exec_list_iterator, iter, signatures) {
+ ir_function_signature *const sig =
+ (ir_function_signature *) iter.get();
+
+ if (parameter_lists_match_exact(&sig->parameters, actual_parameters))
+ return sig;
+ }
+ return NULL;
+}