101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2010 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2101e04c3fSmrg * DEALINGS IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "glsl_symbol_table.h"
2501e04c3fSmrg#include "glsl_parser_extras.h"
2601e04c3fSmrg#include "ir.h"
2701e04c3fSmrg#include "program.h"
2801e04c3fSmrg#include "util/set.h"
2901e04c3fSmrg#include "util/hash_table.h"
3001e04c3fSmrg#include "linker.h"
3101e04c3fSmrg#include "main/mtypes.h"
3201e04c3fSmrg
3301e04c3fSmrgstatic ir_function_signature *
3401e04c3fSmrgfind_matching_signature(const char *name, const exec_list *actual_parameters,
3501e04c3fSmrg                        glsl_symbol_table *symbols);
3601e04c3fSmrg
3701e04c3fSmrgnamespace {
3801e04c3fSmrg
3901e04c3fSmrgclass call_link_visitor : public ir_hierarchical_visitor {
4001e04c3fSmrgpublic:
4101e04c3fSmrg   call_link_visitor(gl_shader_program *prog, gl_linked_shader *linked,
4201e04c3fSmrg		     gl_shader **shader_list, unsigned num_shaders)
4301e04c3fSmrg   {
4401e04c3fSmrg      this->prog = prog;
4501e04c3fSmrg      this->shader_list = shader_list;
4601e04c3fSmrg      this->num_shaders = num_shaders;
4701e04c3fSmrg      this->success = true;
4801e04c3fSmrg      this->linked = linked;
4901e04c3fSmrg
507e102996Smaya      this->locals = _mesa_pointer_set_create(NULL);
5101e04c3fSmrg   }
5201e04c3fSmrg
5301e04c3fSmrg   ~call_link_visitor()
5401e04c3fSmrg   {
5501e04c3fSmrg      _mesa_set_destroy(this->locals, NULL);
5601e04c3fSmrg   }
5701e04c3fSmrg
5801e04c3fSmrg   virtual ir_visitor_status visit(ir_variable *ir)
5901e04c3fSmrg   {
6001e04c3fSmrg      _mesa_set_add(locals, ir);
6101e04c3fSmrg      return visit_continue;
6201e04c3fSmrg   }
6301e04c3fSmrg
6401e04c3fSmrg   virtual ir_visitor_status visit_enter(ir_call *ir)
6501e04c3fSmrg   {
6601e04c3fSmrg      /* If ir is an ir_call from a function that was imported from another
6701e04c3fSmrg       * shader callee will point to an ir_function_signature in the original
6801e04c3fSmrg       * shader.  In this case the function signature MUST NOT BE MODIFIED.
6901e04c3fSmrg       * Doing so will modify the original shader.  This may prevent that
7001e04c3fSmrg       * shader from being linkable in other programs.
7101e04c3fSmrg       */
7201e04c3fSmrg      const ir_function_signature *const callee = ir->callee;
7301e04c3fSmrg      assert(callee != NULL);
7401e04c3fSmrg      const char *const name = callee->function_name();
7501e04c3fSmrg
7601e04c3fSmrg      /* We don't actually need to find intrinsics; they're not real */
7701e04c3fSmrg      if (callee->is_intrinsic())
7801e04c3fSmrg         return visit_continue;
7901e04c3fSmrg
8001e04c3fSmrg      /* Determine if the requested function signature already exists in the
8101e04c3fSmrg       * final linked shader.  If it does, use it as the target of the call.
8201e04c3fSmrg       */
8301e04c3fSmrg      ir_function_signature *sig =
8401e04c3fSmrg         find_matching_signature(name, &callee->parameters, linked->symbols);
8501e04c3fSmrg      if (sig != NULL) {
8601e04c3fSmrg	 ir->callee = sig;
8701e04c3fSmrg	 return visit_continue;
8801e04c3fSmrg      }
8901e04c3fSmrg
9001e04c3fSmrg      /* Try to find the signature in one of the other shaders that is being
9101e04c3fSmrg       * linked.  If it's not found there, return an error.
9201e04c3fSmrg       */
9301e04c3fSmrg      for (unsigned i = 0; i < num_shaders; i++) {
9401e04c3fSmrg         sig = find_matching_signature(name, &ir->actual_parameters,
9501e04c3fSmrg                                       shader_list[i]->symbols);
9601e04c3fSmrg         if (sig)
9701e04c3fSmrg            break;
9801e04c3fSmrg      }
9901e04c3fSmrg
10001e04c3fSmrg      if (sig == NULL) {
10101e04c3fSmrg	 /* FINISHME: Log the full signature of unresolved function.
10201e04c3fSmrg	  */
10301e04c3fSmrg	 linker_error(this->prog, "unresolved reference to function `%s'\n",
10401e04c3fSmrg		      name);
10501e04c3fSmrg	 this->success = false;
10601e04c3fSmrg	 return visit_stop;
10701e04c3fSmrg      }
10801e04c3fSmrg
10901e04c3fSmrg      /* Find the prototype information in the linked shader.  Generate any
11001e04c3fSmrg       * details that may be missing.
11101e04c3fSmrg       */
11201e04c3fSmrg      ir_function *f = linked->symbols->get_function(name);
11301e04c3fSmrg      if (f == NULL) {
11401e04c3fSmrg	 f = new(linked) ir_function(name);
11501e04c3fSmrg
11601e04c3fSmrg	 /* Add the new function to the linked IR.  Put it at the end
11701e04c3fSmrg          * so that it comes after any global variable declarations
11801e04c3fSmrg          * that it refers to.
11901e04c3fSmrg	  */
12001e04c3fSmrg	 linked->symbols->add_function(f);
12101e04c3fSmrg	 linked->ir->push_tail(f);
12201e04c3fSmrg      }
12301e04c3fSmrg
12401e04c3fSmrg      ir_function_signature *linked_sig =
12501e04c3fSmrg	 f->exact_matching_signature(NULL, &callee->parameters);
12601e04c3fSmrg      if (linked_sig == NULL) {
12701e04c3fSmrg	 linked_sig = new(linked) ir_function_signature(callee->return_type);
12801e04c3fSmrg	 f->add_signature(linked_sig);
12901e04c3fSmrg      }
13001e04c3fSmrg
13101e04c3fSmrg      /* At this point linked_sig and called may be the same.  If ir is an
13201e04c3fSmrg       * ir_call from linked then linked_sig and callee will be
13301e04c3fSmrg       * ir_function_signatures that have no definitions (is_defined is false).
13401e04c3fSmrg       */
13501e04c3fSmrg      assert(!linked_sig->is_defined);
13601e04c3fSmrg      assert(linked_sig->body.is_empty());
13701e04c3fSmrg
13801e04c3fSmrg      /* Create an in-place clone of the function definition.  This multistep
13901e04c3fSmrg       * process introduces some complexity here, but it has some advantages.
14001e04c3fSmrg       * The parameter list and the and function body are cloned separately.
14101e04c3fSmrg       * The clone of the parameter list is used to prime the hashtable used
14201e04c3fSmrg       * to replace variable references in the cloned body.
14301e04c3fSmrg       *
14401e04c3fSmrg       * The big advantage is that the ir_function_signature does not change.
14501e04c3fSmrg       * This means that we don't have to process the rest of the IR tree to
14601e04c3fSmrg       * patch ir_call nodes.  In addition, there is no way to remove or
14701e04c3fSmrg       * replace signature stored in a function.  One could easily be added,
14801e04c3fSmrg       * but this avoids the need.
14901e04c3fSmrg       */
1507e102996Smaya      struct hash_table *ht = _mesa_pointer_hash_table_create(NULL);
15101e04c3fSmrg
15201e04c3fSmrg      exec_list formal_parameters;
15301e04c3fSmrg      foreach_in_list(const ir_instruction, original, &sig->parameters) {
15401e04c3fSmrg         assert(const_cast<ir_instruction *>(original)->as_variable());
15501e04c3fSmrg
15601e04c3fSmrg         ir_instruction *copy = original->clone(linked, ht);
15701e04c3fSmrg         formal_parameters.push_tail(copy);
15801e04c3fSmrg      }
15901e04c3fSmrg
16001e04c3fSmrg      linked_sig->replace_parameters(&formal_parameters);
16101e04c3fSmrg
16201e04c3fSmrg      linked_sig->intrinsic_id = sig->intrinsic_id;
16301e04c3fSmrg
16401e04c3fSmrg      if (sig->is_defined) {
16501e04c3fSmrg         foreach_in_list(const ir_instruction, original, &sig->body) {
16601e04c3fSmrg            ir_instruction *copy = original->clone(linked, ht);
16701e04c3fSmrg            linked_sig->body.push_tail(copy);
16801e04c3fSmrg         }
16901e04c3fSmrg
17001e04c3fSmrg         linked_sig->is_defined = true;
17101e04c3fSmrg      }
17201e04c3fSmrg
17301e04c3fSmrg      _mesa_hash_table_destroy(ht, NULL);
17401e04c3fSmrg
17501e04c3fSmrg      /* Patch references inside the function to things outside the function
17601e04c3fSmrg       * (i.e., function calls and global variables).
17701e04c3fSmrg       */
17801e04c3fSmrg      linked_sig->accept(this);
17901e04c3fSmrg
18001e04c3fSmrg      ir->callee = linked_sig;
18101e04c3fSmrg
18201e04c3fSmrg      return visit_continue;
18301e04c3fSmrg   }
18401e04c3fSmrg
18501e04c3fSmrg   virtual ir_visitor_status visit_leave(ir_call *ir)
18601e04c3fSmrg   {
18701e04c3fSmrg      /* Traverse list of function parameters, and for array parameters
18801e04c3fSmrg       * propagate max_array_access. Otherwise arrays that are only referenced
18901e04c3fSmrg       * from inside functions via function parameters will be incorrectly
19001e04c3fSmrg       * optimized. This will lead to incorrect code being generated (or worse).
19101e04c3fSmrg       * Do it when leaving the node so the children would propagate their
19201e04c3fSmrg       * array accesses first.
19301e04c3fSmrg       */
19401e04c3fSmrg
19501e04c3fSmrg      const exec_node *formal_param_node = ir->callee->parameters.get_head();
19601e04c3fSmrg      if (formal_param_node) {
19701e04c3fSmrg         const exec_node *actual_param_node = ir->actual_parameters.get_head();
19801e04c3fSmrg         while (!actual_param_node->is_tail_sentinel()) {
19901e04c3fSmrg            ir_variable *formal_param = (ir_variable *) formal_param_node;
20001e04c3fSmrg            ir_rvalue *actual_param = (ir_rvalue *) actual_param_node;
20101e04c3fSmrg
20201e04c3fSmrg            formal_param_node = formal_param_node->get_next();
20301e04c3fSmrg            actual_param_node = actual_param_node->get_next();
20401e04c3fSmrg
20501e04c3fSmrg            if (formal_param->type->is_array()) {
20601e04c3fSmrg               ir_dereference_variable *deref = actual_param->as_dereference_variable();
20701e04c3fSmrg               if (deref && deref->var && deref->var->type->is_array()) {
20801e04c3fSmrg                  deref->var->data.max_array_access =
20901e04c3fSmrg                     MAX2(formal_param->data.max_array_access,
21001e04c3fSmrg                         deref->var->data.max_array_access);
21101e04c3fSmrg               }
21201e04c3fSmrg            }
21301e04c3fSmrg         }
21401e04c3fSmrg      }
21501e04c3fSmrg      return visit_continue;
21601e04c3fSmrg   }
21701e04c3fSmrg
21801e04c3fSmrg   virtual ir_visitor_status visit(ir_dereference_variable *ir)
21901e04c3fSmrg   {
22001e04c3fSmrg      if (_mesa_set_search(locals, ir->var) == NULL) {
22101e04c3fSmrg	 /* The non-function variable must be a global, so try to find the
22201e04c3fSmrg	  * variable in the shader's symbol table.  If the variable is not
22301e04c3fSmrg	  * found, then it's a global that *MUST* be defined in the original
22401e04c3fSmrg	  * shader.
22501e04c3fSmrg	  */
22601e04c3fSmrg	 ir_variable *var = linked->symbols->get_variable(ir->var->name);
22701e04c3fSmrg	 if (var == NULL) {
22801e04c3fSmrg	    /* Clone the ir_variable that the dereference already has and add
22901e04c3fSmrg	     * it to the linked shader.
23001e04c3fSmrg	     */
23101e04c3fSmrg	    var = ir->var->clone(linked, NULL);
23201e04c3fSmrg	    linked->symbols->add_variable(var);
23301e04c3fSmrg	    linked->ir->push_head(var);
23401e04c3fSmrg	 } else {
23501e04c3fSmrg            if (var->type->is_array()) {
23601e04c3fSmrg               /* It is possible to have a global array declared in multiple
23701e04c3fSmrg                * shaders without a size.  The array is implicitly sized by
23801e04c3fSmrg                * the maximal access to it in *any* shader.  Because of this,
23901e04c3fSmrg                * we need to track the maximal access to the array as linking
24001e04c3fSmrg                * pulls more functions in that access the array.
24101e04c3fSmrg                */
24201e04c3fSmrg               var->data.max_array_access =
24301e04c3fSmrg                  MAX2(var->data.max_array_access,
24401e04c3fSmrg                       ir->var->data.max_array_access);
24501e04c3fSmrg
24601e04c3fSmrg               if (var->type->length == 0 && ir->var->type->length != 0)
24701e04c3fSmrg                  var->type = ir->var->type;
24801e04c3fSmrg            }
24901e04c3fSmrg            if (var->is_interface_instance()) {
25001e04c3fSmrg               /* Similarly, we need implicit sizes of arrays within interface
25101e04c3fSmrg                * blocks to be sized by the maximal access in *any* shader.
25201e04c3fSmrg                */
25301e04c3fSmrg               int *const linked_max_ifc_array_access =
25401e04c3fSmrg                  var->get_max_ifc_array_access();
25501e04c3fSmrg               int *const ir_max_ifc_array_access =
25601e04c3fSmrg                  ir->var->get_max_ifc_array_access();
25701e04c3fSmrg
25801e04c3fSmrg               assert(linked_max_ifc_array_access != NULL);
25901e04c3fSmrg               assert(ir_max_ifc_array_access != NULL);
26001e04c3fSmrg
26101e04c3fSmrg               for (unsigned i = 0; i < var->get_interface_type()->length;
26201e04c3fSmrg                    i++) {
26301e04c3fSmrg                  linked_max_ifc_array_access[i] =
26401e04c3fSmrg                     MAX2(linked_max_ifc_array_access[i],
26501e04c3fSmrg                          ir_max_ifc_array_access[i]);
26601e04c3fSmrg               }
26701e04c3fSmrg            }
26801e04c3fSmrg	 }
26901e04c3fSmrg
27001e04c3fSmrg	 ir->var = var;
27101e04c3fSmrg      }
27201e04c3fSmrg
27301e04c3fSmrg      return visit_continue;
27401e04c3fSmrg   }
27501e04c3fSmrg
27601e04c3fSmrg   /** Was function linking successful? */
27701e04c3fSmrg   bool success;
27801e04c3fSmrg
27901e04c3fSmrgprivate:
28001e04c3fSmrg   /**
28101e04c3fSmrg    * Shader program being linked
28201e04c3fSmrg    *
28301e04c3fSmrg    * This is only used for logging error messages.
28401e04c3fSmrg    */
28501e04c3fSmrg   gl_shader_program *prog;
28601e04c3fSmrg
28701e04c3fSmrg   /** List of shaders available for linking. */
28801e04c3fSmrg   gl_shader **shader_list;
28901e04c3fSmrg
29001e04c3fSmrg   /** Number of shaders available for linking. */
29101e04c3fSmrg   unsigned num_shaders;
29201e04c3fSmrg
29301e04c3fSmrg   /**
29401e04c3fSmrg    * Final linked shader
29501e04c3fSmrg    *
29601e04c3fSmrg    * This is used two ways.  It is used to find global variables in the
29701e04c3fSmrg    * linked shader that are accessed by the function.  It is also used to add
29801e04c3fSmrg    * global variables from the shader where the function originated.
29901e04c3fSmrg    */
30001e04c3fSmrg   gl_linked_shader *linked;
30101e04c3fSmrg
30201e04c3fSmrg   /**
30301e04c3fSmrg    * Table of variables local to the function.
30401e04c3fSmrg    */
30501e04c3fSmrg   set *locals;
30601e04c3fSmrg};
30701e04c3fSmrg
30801e04c3fSmrg} /* anonymous namespace */
30901e04c3fSmrg
31001e04c3fSmrg/**
31101e04c3fSmrg * Searches a list of shaders for a particular function definition
31201e04c3fSmrg */
31301e04c3fSmrgir_function_signature *
31401e04c3fSmrgfind_matching_signature(const char *name, const exec_list *actual_parameters,
31501e04c3fSmrg                        glsl_symbol_table *symbols)
31601e04c3fSmrg{
31701e04c3fSmrg   ir_function *const f = symbols->get_function(name);
31801e04c3fSmrg
31901e04c3fSmrg   if (f) {
32001e04c3fSmrg      ir_function_signature *sig =
32101e04c3fSmrg         f->matching_signature(NULL, actual_parameters, false);
32201e04c3fSmrg
32301e04c3fSmrg      if (sig && (sig->is_defined || sig->is_intrinsic()))
32401e04c3fSmrg         return sig;
32501e04c3fSmrg   }
32601e04c3fSmrg
32701e04c3fSmrg   return NULL;
32801e04c3fSmrg}
32901e04c3fSmrg
33001e04c3fSmrg
33101e04c3fSmrgbool
33201e04c3fSmrglink_function_calls(gl_shader_program *prog, gl_linked_shader *main,
33301e04c3fSmrg		    gl_shader **shader_list, unsigned num_shaders)
33401e04c3fSmrg{
33501e04c3fSmrg   call_link_visitor v(prog, main, shader_list, num_shaders);
33601e04c3fSmrg
33701e04c3fSmrg   v.run(main->ir);
33801e04c3fSmrg   return v.success;
33901e04c3fSmrg}
340