X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fglsl%2Flink_functions.cpp;h=6b3e154488aef5e53d10466bb5bc7f48f3aaa9ed;hb=7214451bdce6d553620d2b9b3f1f89d14b113357;hp=a9ed49a3492cd098ccc95b63091856a30dbd6c72;hpb=afe125e0a18ac3886c45c7e6b02b122fb2d327b5;p=mesa.git diff --git a/src/glsl/link_functions.cpp b/src/glsl/link_functions.cpp index a9ed49a3492..6b3e154488a 100644 --- a/src/glsl/link_functions.cpp +++ b/src/glsl/link_functions.cpp @@ -21,25 +21,18 @@ * DEALINGS IN THE SOFTWARE. */ -#include -#include -#include - -extern "C" { -#include -} - -#include "main/mtypes.h" +#include "main/core.h" #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ir.h" #include "program.h" -#include "hash_table.h" +#include "program/hash_table.h" #include "linker.h" static ir_function_signature * find_matching_signature(const char *name, const exec_list *actual_parameters, - gl_shader **shader_list, unsigned num_shaders); + gl_shader **shader_list, unsigned num_shaders, + bool use_builtin); class call_link_visitor : public ir_hierarchical_visitor { public: @@ -75,7 +68,7 @@ public: * Doing so will modify the original shader. This may prevent that * shader from being linkable in other programs. */ - const ir_function_signature *const callee = ir->get_callee(); + const ir_function_signature *const callee = ir->callee; assert(callee != NULL); const char *const name = callee->function_name(); @@ -83,9 +76,10 @@ public: * final linked shader. If it does, use it as the target of the call. */ ir_function_signature *sig = - find_matching_signature(name, &callee->parameters, &linked, 1); + find_matching_signature(name, &callee->parameters, &linked, 1, + ir->use_builtin); if (sig != NULL) { - ir->set_callee(sig); + ir->callee = sig; return visit_continue; } @@ -93,12 +87,12 @@ public: * linked. If it's not found there, return an error. */ sig = find_matching_signature(name, &ir->actual_parameters, shader_list, - num_shaders); + num_shaders, ir->use_builtin); if (sig == NULL) { /* FINISHME: Log the full signature of unresolved function. */ - linker_error_printf(this->prog, "unresolved reference to function " - "`%s'\n", name); + linker_error(this->prog, "unresolved reference to function `%s'\n", + name); this->success = false; return visit_stop; } @@ -107,12 +101,22 @@ public: * details that may be missing. */ ir_function *f = linked->symbols->get_function(name); - if (f == NULL) + if (f == NULL) { f = new(linked) ir_function(name); + /* Add the new function to the linked IR. Put it at the end + * so that it comes after any global variable declarations + * that it refers to. + */ + linked->symbols->add_function(f); + linked->ir->push_tail(f); + } + ir_function_signature *linked_sig = - f->matching_signature(&callee->parameters); - if (linked_sig == NULL) { + f->exact_matching_signature(&callee->parameters); + if ((linked_sig == NULL) + || ((linked_sig != NULL) + && (linked_sig->is_builtin != ir->use_builtin))) { linked_sig = new(linked) ir_function_signature(callee->return_type); f->add_signature(linked_sig); } @@ -143,7 +147,7 @@ public: const ir_instruction *const original = (ir_instruction *) node; assert(const_cast(original)->as_variable()); - ir_instruction *copy = original->clone(ht); + ir_instruction *copy = original->clone(linked, ht); formal_parameters.push_tail(copy); } @@ -152,7 +156,7 @@ public: foreach_list_const(node, &sig->body) { const ir_instruction *const original = (ir_instruction *) node; - ir_instruction *copy = original->clone(ht); + ir_instruction *copy = original->clone(linked, ht); linked_sig->body.push_tail(copy); } @@ -164,6 +168,8 @@ public: */ linked_sig->accept(this); + ir->callee = linked_sig; + return visit_continue; } @@ -180,9 +186,21 @@ public: /* Clone the ir_variable that the dereference already has and add * it to the linked shader. */ - var = ir->var->clone(NULL); - linked->symbols->add_variable(var->name, var); + var = ir->var->clone(linked, NULL); + linked->symbols->add_variable(var); linked->ir->push_head(var); + } else if (var->type->is_array()) { + /* It is possible to have a global array declared in multiple + * shaders without a size. The array is implicitly sized by the + * maximal access to it in *any* shader. Because of this, we + * need to track the maximal access to the array as linking pulls + * more functions in that access the array. + */ + var->max_array_access = + MAX2(var->max_array_access, ir->var->max_array_access); + + if (var->type->length == 0 && ir->var->type->length != 0) + var->type = ir->var->type; } ir->var = var; @@ -229,7 +247,8 @@ private: */ ir_function_signature * find_matching_signature(const char *name, const exec_list *actual_parameters, - gl_shader **shader_list, unsigned num_shaders) + gl_shader **shader_list, unsigned num_shaders, + bool use_builtin) { for (unsigned i = 0; i < num_shaders; i++) { ir_function *const f = shader_list[i]->symbols->get_function(name); @@ -242,6 +261,13 @@ find_matching_signature(const char *name, const exec_list *actual_parameters, if ((sig == NULL) || !sig->is_defined) continue; + /* If this function expects to bind to a built-in function and the + * signature that we found isn't a built-in, keep looking. Also keep + * looking if we expect a non-built-in but found a built-in. + */ + if (use_builtin != sig->is_builtin) + continue; + return sig; }