glsl: Only create one ir_function for a given name.

Piglit's spec/glsl-1.10/linker/override-builtin-{const,uniform}-05 tests
do the following:

1. Call abs(float) - a built-in function.
2. Create a user-defined replacement for abs(float).
3. Call abs(float) again - now the user function.

At step 1, we created an ir_function which included the built-in
signature, added it to the symbol table, and emitted it into the IR
stream.

Then, when processing the function definition at step 2, we'd see that
there was already an ir_function.  But, since there were no user-defined
functions, we skipped over a bunch of code, and ended up creating a
second one.  This new ir_function shadowed the original in the symbol
table, but both ended up in the IR stream.

This results in an awkward situation where searching for an ir_function
via the symbol table, a forward linked list walk, and a reverse linked
list walk may return different ir_functions.  This seems undesirable.

This patch instead re-uses the existing ir_function, putting both
built-in and user-defined signatures in the same one.  The previous
patch's additional filtering ensures everything continues working.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
Kenneth Graunke 2014-07-24 14:05:41 -07:00
parent 21129d4de3
commit 3d051772c8

View file

@ -4110,12 +4110,27 @@ ast_function::hir(exec_list *instructions,
name);
}
/* Create an ir_function if one doesn't already exist. */
f = state->symbols->get_function(name);
if (f == NULL) {
f = new(ctx) ir_function(name);
if (!state->symbols->add_function(f)) {
/* This function name shadows a non-function use of the same name. */
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
"non-function", name);
return NULL;
}
emit_function(state, f);
}
/* Verify that this function's signature either doesn't match a previously
* 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.
*/
f = state->symbols->get_function(name);
if (f != NULL && (state->es_shader || f->has_user_signature())) {
if (state->es_shader || f->has_user_signature()) {
sig = f->exact_matching_signature(state, &hir_parameters);
if (sig != NULL) {
const char *badvar = sig->qualifiers_match(&hir_parameters);
@ -4146,18 +4161,6 @@ ast_function::hir(exec_list *instructions,
}
}
}
} else {
f = new(ctx) ir_function(name);
if (!state->symbols->add_function(f)) {
/* This function name shadows a non-function use of the same name. */
YYLTYPE loc = this->get_location();
_mesa_glsl_error(&loc, state, "function name `%s' conflicts with "
"non-function", name);
return NULL;
}
emit_function(state, f);
}
/* Verify the return type of main() */