summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-03-31 18:23:21 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-03-31 18:23:21 -0700
commit92318a947958892497722772b03c643ebc943294 (patch)
tree587010b36f066b2fe77dd638353d7a9b954335d6
parentacce380a3f6df56d44460c0b066b4791cc0f9732 (diff)
Add ast_function::hir
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
-rw-r--r--ast.h26
-rw-r--r--ast_to_hir.cpp65
-rw-r--r--glsl_parser_extras.cpp1
3 files changed, 68 insertions, 24 deletions
diff --git a/ast.h b/ast.h
index d21be7e..8035259 100644
--- 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;
};
diff --git a/ast_to_hir.cpp b/ast_to_hir.cpp
index 6d78383..2eecc9f 100644
--- a/ast_to_hir.cpp
+++ b/ast_to_hir.cpp
@@ -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;
}
diff --git a/glsl_parser_extras.cpp b/glsl_parser_extras.cpp
index 1ddc2ee..265782e 100644
--- a/glsl_parser_extras.cpp
+++ b/glsl_parser_extras.cpp
@@ -327,6 +327,7 @@ ast_function::print(void) const
ast_function::ast_function(void)
+ : is_definition(false), signature(NULL)
{
make_empty_list(& parameters);
}