Add ast_function::hir
authorIan Romanick <ian.d.romanick@intel.com>
Thu, 1 Apr 2010 01:23:21 +0000 (18:23 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Thu, 1 Apr 2010 01:23:21 +0000 (18:23 -0700)
ast_function::hir consists of bits pulled out of
ast_function_definition::hir.  In fact, the later uses the former to
do a lot of its processing.  Several class private data fields were
added to ast_function to facilitate communicate between the two.

This causes the following tests to pass:

    glslparsertest/shaders/CorrectModule.frag

This causes the following tests to fail.  These shaders were
previously failing to compile, but they were all failing for the wrong
reasons.

    glslparsertest/shaders/function9.frag
    glslparsertest/shaders/function10.frag

ast.h
ast_to_hir.cpp
glsl_parser_extras.cpp

diff --git a/ast.h b/ast.h
index d21be7e7a091edcc10f520f4ed2e73514d94f063..80352590080f5ffc1672dbdb10fe6c77f4c2b675 100644 (file)
--- a/ast.h
+++ b/ast.h
@@ -444,10 +444,36 @@ public:
 
    virtual void print(void) const;
 
+   virtual ir_rvalue *hir(exec_list *instructions,
+                         struct _mesa_glsl_parse_state *state);
+
    ast_fully_specified_type *return_type;
    char *identifier;
 
    struct simple_node parameters;
+
+private:
+   /**
+    * Is this prototype part of the function definition?
+    *
+    * Used by ast_function_definition::hir to process the parameters, etc.
+    * of the function.
+    *
+    * \sa ::hir
+    */
+   bool is_definition;
+
+   /**
+    * Function signature corresponding to this function prototype instance
+    *
+    * Used by ast_function_definition::hir to process the parameters, etc.
+    * of the function.
+    *
+    * \sa ::hir
+    */
+   class ir_function_signature *signature;
+
+   friend class ast_function_definition;
 };
 
 
index 6d78383a46c5b4523db116f50eede5a57d76b943..2eecc9f3ec9668cc5dc1a9381c2bc5a314fefef8 100644 (file)
@@ -1445,26 +1445,28 @@ parameter_lists_match(exec_list *list_a, exec_list *list_b)
 
 
 ir_rvalue *
-ast_function_definition::hir(exec_list *instructions,
-                            struct _mesa_glsl_parse_state *state)
+ast_function::hir(exec_list *instructions,
+                 struct _mesa_glsl_parse_state *state)
 {
-   ir_label *label;
-   ir_function_signature *signature = NULL;
    ir_function *f = NULL;
-   exec_list parameters;
+   ir_function_signature *sig = NULL;
+   exec_list hir_parameters;
 
 
+   /* The prototype part of a function does not generate anything in the IR
+    * instruction stream.
+    */
+   (void) instructions;
+
    /* Convert the list of function parameters to HIR now so that they can be
     * used below to compare this function's signature with previously seen
     * signatures for functions with the same name.
     */
-   ast_function_parameters_to_hir(& this->prototype->parameters, & parameters,
-                                 state);
+   ast_function_parameters_to_hir(& this->parameters, & hir_parameters, state);
 
    const char *return_type_name;
    const glsl_type *return_type =
-      this->prototype->return_type->specifier->glsl_type(& return_type_name,
-                                                        state);
+      this->return_type->specifier->glsl_type(& return_type_name, state);
 
    assert(return_type != NULL);
 
@@ -1472,30 +1474,30 @@ ast_function_definition::hir(exec_list *instructions,
     * seen signature for a function with the same name, or, if a match is found,
     * that the previously seen signature does not have an associated definition.
     */
-   const char *const name = this->prototype->identifier;
+   const char *const name = identifier;
    f = state->symbols->get_function(name);
    if (f != NULL) {
       foreach_iter(exec_list_iterator, iter, *f) {
-        signature = (struct ir_function_signature *) iter.get();
+        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(& parameters, & signature->parameters)) {
+        if (parameter_lists_match(& hir_parameters, & sig->parameters)) {
            /* FINISHME: Compare return types. */
 
-           if (signature->definition != NULL) {
+           if (is_definition && (sig->definition != NULL)) {
               YYLTYPE loc = this->get_location();
 
               _mesa_glsl_error(& loc, state, "function `%s' redefined", name);
-              signature = NULL;
+              sig = NULL;
               break;
            }
         }
 
-        signature = NULL;
+        sig = NULL;
       }
 
    } else if (state->symbols->name_declared_this_scope(name)) {
@@ -1505,7 +1507,7 @@ ast_function_definition::hir(exec_list *instructions,
 
       _mesa_glsl_error(& loc, state, "function name `%s' conflicts with "
                       "non-function", name);
-      signature = NULL;
+      sig = NULL;
    } else {
       f = new ir_function(name);
       state->symbols->add_function(f->name, f);
@@ -1519,7 +1521,7 @@ ast_function_definition::hir(exec_list *instructions,
         _mesa_glsl_error(& loc, state, "main() must return void");
       }
 
-      if (!parameters.is_empty()) {
+      if (!hir_parameters.is_empty()) {
         YYLTYPE loc = this->get_location();
 
         _mesa_glsl_error(& loc, state, "main() must not take any parameters");
@@ -1528,15 +1530,15 @@ ast_function_definition::hir(exec_list *instructions,
 
    /* Finish storing the information about this new function in its signature.
     */
-   if (signature == NULL) {
-      signature = new ir_function_signature(return_type);
-      f->add_signature(signature);
-   } else {
+   if (sig == NULL) {
+      sig = new ir_function_signature(return_type);
+      f->add_signature(sig);
+   } else if (is_definition) {
       /* Destroy all of the previous parameter information.  The previous
        * parameter information comes from the function prototype, and it can
        * either include invalid parameter names or may not have names at all.
        */
-      foreach_iter(exec_list_iterator, iter, signature->parameters) {
+      foreach_iter(exec_list_iterator, iter, sig->parameters) {
         assert(((ir_instruction *) iter.get())->as_variable() != NULL);
 
         iter.remove();
@@ -1544,13 +1546,28 @@ ast_function_definition::hir(exec_list *instructions,
       }
    }
 
-   parameters.move_nodes_to(& signature->parameters);
+   hir_parameters.move_nodes_to(& sig->parameters);
+   signature = sig;
+
+   /* Function declarations (prototypes) do not have r-values.
+    */
+   return NULL;
+}
+
+
+ir_rvalue *
+ast_function_definition::hir(exec_list *instructions,
+                            struct _mesa_glsl_parse_state *state)
+{
+   prototype->is_definition = true;
+   prototype->hir(instructions, state);
 
+   ir_function_signature *signature = prototype->signature;
 
    assert(state->current_function == NULL);
    state->current_function = signature;
 
-   label = new ir_label(name);
+   ir_label *label = new ir_label(signature->function_name());
    if (signature->definition == NULL) {
       signature->definition = label;
    }
index 1ddc2ee9ddd221a54187ef1aeb559f2ff0531370..265782ebdabf8ac971e555c4f786d2ca8ee34412 100644 (file)
@@ -327,6 +327,7 @@ ast_function::print(void) const
 
 
 ast_function::ast_function(void)
+   : is_definition(false), signature(NULL)
 {
    make_empty_list(& parameters);
 }