summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Graunke <kenneth@whitecape.org>2010-12-06 10:54:21 -0800
committerKenneth Graunke <kenneth@whitecape.org>2010-12-06 13:43:22 -0800
commitc17c7903871b031162e41d6495a1bef64844e19b (patch)
treed3a89af48859453542f8e44f2fcc8c78a19c248e
parenta8f52647b045b5400ebcfc58ba235599a6e9ad87 (diff)
glsl: Properly add functions during lazy built-in prototype importing.
The original lazy built-in importing patch did not add the newly created function to the symbol table, nor actually emit it into the IR stream. Adding it to the symbol table is non-trivial since importing occurs when generating some ir_call in a nested scope. A new add_global_function method, backed by new symbol_table code in the previous patch, handles this. Fixes bug #32030.
-rw-r--r--src/glsl/ast_function.cpp20
-rw-r--r--src/glsl/glsl_symbol_table.cpp7
-rw-r--r--src/glsl/glsl_symbol_table.h5
3 files changed, 25 insertions, 7 deletions
diff --git a/src/glsl/ast_function.cpp b/src/glsl/ast_function.cpp
index 1dd210a679..6ecf779c93 100644
--- a/src/glsl/ast_function.cpp
+++ b/src/glsl/ast_function.cpp
@@ -99,23 +99,29 @@ match_function_by_name(exec_list *instructions, const char *name,
{
void *ctx = state;
ir_function *f = state->symbols->get_function(name);
- ir_function_signature *sig = NULL;
+ ir_function_signature *sig;
+
+ sig = f ? f->matching_signature(actual_parameters) : NULL;
/* FINISHME: This doesn't handle the case where shader X contains a
* FINISHME: matching signature but shader X + N contains an _exact_
* FINISHME: matching signature.
*/
- if (f != NULL) {
- sig = f->matching_signature(actual_parameters);
- } else if (state->symbols->get_type(name) == NULL && (state->language_version == 110 || state->symbols->get_variable(name) == NULL)) {
+ if (sig == NULL && (f == NULL || state->es_shader || !f->has_user_signature()) && state->symbols->get_type(name) == NULL && (state->language_version == 110 || state->symbols->get_variable(name) == NULL)) {
/* The current shader doesn't contain a matching function or signature.
* Before giving up, look for the prototype in the built-in functions.
*/
for (unsigned i = 0; i < state->num_builtins_to_link; i++) {
- f = state->builtins_to_link[i]->symbols->get_function(name);
- sig = f ? f->matching_signature(actual_parameters) : NULL;
+ ir_function *builtin;
+ builtin = state->builtins_to_link[i]->symbols->get_function(name);
+ sig = builtin ? builtin->matching_signature(actual_parameters) : NULL;
if (sig != NULL) {
- f = new(ctx) ir_function(name);
+ if (f == NULL) {
+ f = new(ctx) ir_function(name);
+ state->symbols->add_global_function(f);
+ emit_function(state, instructions, f);
+ }
+
f->add_signature(sig->clone_prototype(f, NULL));
break;
}
diff --git a/src/glsl/glsl_symbol_table.cpp b/src/glsl/glsl_symbol_table.cpp
index fb22a17ce5..3dcd928016 100644
--- a/src/glsl/glsl_symbol_table.cpp
+++ b/src/glsl/glsl_symbol_table.cpp
@@ -135,6 +135,13 @@ bool glsl_symbol_table::add_function(ir_function *f)
return _mesa_symbol_table_add_symbol(table, -1, f->name, entry) == 0;
}
+void glsl_symbol_table::add_global_function(ir_function *f)
+{
+ symbol_table_entry *entry = new(mem_ctx) symbol_table_entry(f);
+ int added = _mesa_symbol_table_add_global_symbol(table, -1, f->name, entry);
+ assert(added == 0);
+}
+
ir_variable *glsl_symbol_table::get_variable(const char *name)
{
symbol_table_entry *entry = get_entry(name);
diff --git a/src/glsl/glsl_symbol_table.h b/src/glsl/glsl_symbol_table.h
index 329cd106b1..28a44ebe91 100644
--- a/src/glsl/glsl_symbol_table.h
+++ b/src/glsl/glsl_symbol_table.h
@@ -103,6 +103,11 @@ public:
/*@}*/
/**
+ * Add an function at global scope without checking for scoping conflicts.
+ */
+ void add_global_function(ir_function *f);
+
+ /**
* \name Methods to get symbols from the table
*/
/*@{*/