[Mesa-dev] [PATCH 2/9] glsl: Split up function matching and call generation a bit more.

Kenneth Graunke kenneth at whitecape.org
Wed Mar 28 20:33:01 PDT 2012


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 at whitecape.org>
---
 src/glsl/ast_function.cpp |   82 +++++++++++++++++++++++++-------------------
 1 files changed, 47 insertions(+), 35 deletions(-)

It's probably easier to apply this and compare rather than reading the
raw diff itself.

diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 1c2e861..2ad8fba 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'
-- 
1.7.7.6



More information about the mesa-dev mailing list