18fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick/*
28fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * Copyright © 2010 Intel Corporation
38fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick *
48fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * Permission is hereby granted, free of charge, to any person obtaining a
58fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * copy of this software and associated documentation files (the "Software"),
68fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * to deal in the Software without restriction, including without limitation
78fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * and/or sell copies of the Software, and to permit persons to whom the
98fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * Software is furnished to do so, subject to the following conditions:
108fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick *
118fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * The above copyright notice and this permission notice (including the next
128fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * paragraph) shall be included in all copies or substantial portions of the
138fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * Software.
148fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick *
158fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
188fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
198fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
208fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
218fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick * DEALINGS IN THE SOFTWARE.
228fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick */
238fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
24bfd7c9ac228c7ed8aec04c3b3aa33f40ee00b035Chia-I Wu#include "main/core.h"
258fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick#include "glsl_symbol_table.h"
268fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick#include "glsl_parser_extras.h"
278fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick#include "ir.h"
288fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick#include "program.h"
2931747155ea3a24190277b125bd188ac8689af719Aras Pranckevicius#include "program/hash_table.h"
308fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick#include "linker.h"
318fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
325adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanickstatic ir_function_signature *
335adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanickfind_matching_signature(const char *name, const exec_list *actual_parameters,
3466f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick			gl_shader **shader_list, unsigned num_shaders,
3566f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick			bool use_builtin);
365adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick
378fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanickclass call_link_visitor : public ir_hierarchical_visitor {
388fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanickpublic:
39532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick   call_link_visitor(gl_shader_program *prog, gl_shader *linked,
40532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick		     gl_shader **shader_list, unsigned num_shaders)
418fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   {
428fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      this->prog = prog;
438fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      this->shader_list = shader_list;
448fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      this->num_shaders = num_shaders;
458fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      this->success = true;
46532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      this->linked = linked;
47fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick
48fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      this->locals = hash_table_ctor(0, hash_table_pointer_hash,
49fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick				     hash_table_pointer_compare);
50fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   }
51fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick
52fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   ~call_link_visitor()
53fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   {
54fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      hash_table_dtor(this->locals);
55fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   }
56fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick
57fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   virtual ir_visitor_status visit(ir_variable *ir)
58fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   {
59fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      hash_table_insert(locals, ir, ir);
60fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      return visit_continue;
618fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   }
628fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
638fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   virtual ir_visitor_status visit_enter(ir_call *ir)
648fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   {
65532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      /* If ir is an ir_call from a function that was imported from another
66532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * shader callee will point to an ir_function_signature in the original
67532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * shader.  In this case the function signature MUST NOT BE MODIFIED.
68532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * Doing so will modify the original shader.  This may prevent that
69532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * shader from being linkable in other programs.
708fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       */
7182065fa20ee3f2880a070f1f4f75509b910ceddeKenneth Graunke      const ir_function_signature *const callee = ir->callee;
728fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      assert(callee != NULL);
738fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      const char *const name = callee->function_name();
748fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
75532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      /* Determine if the requested function signature already exists in the
76532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * final linked shader.  If it does, use it as the target of the call.
77532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       */
785adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick      ir_function_signature *sig =
7966f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick	 find_matching_signature(name, &callee->parameters, &linked, 1,
8066f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick				 ir->use_builtin);
81532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      if (sig != NULL) {
8282065fa20ee3f2880a070f1f4f75509b910ceddeKenneth Graunke	 ir->callee = sig;
83532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick	 return visit_continue;
84532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      }
85532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick
86532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      /* Try to find the signature in one of the other shaders that is being
87532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * linked.  If it's not found there, return an error.
88532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       */
89532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      sig = find_matching_signature(name, &ir->actual_parameters, shader_list,
9066f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick				    num_shaders, ir->use_builtin);
918fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      if (sig == NULL) {
928fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	 /* FINISHME: Log the full signature of unresolved function.
938fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	  */
94586e741ac1fa222d041990b265e820f5aa11344dIan Romanick	 linker_error(this->prog, "unresolved reference to function `%s'\n",
95586e741ac1fa222d041990b265e820f5aa11344dIan Romanick		      name);
968fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	 this->success = false;
978fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	 return visit_stop;
988fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      }
998fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
100532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      /* Find the prototype information in the linked shader.  Generate any
101532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * details that may be missing.
102532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       */
103532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      ir_function *f = linked->symbols->get_function(name);
10460f898a90ebd29d2593866faa1f2d6f65961a414Ian Romanick      if (f == NULL) {
105532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick	 f = new(linked) ir_function(name);
10660f898a90ebd29d2593866faa1f2d6f65961a414Ian Romanick
10701a851c296347d8e9d2166b3c83eab97404c0670Paul Berry	 /* Add the new function to the linked IR.  Put it at the end
10801a851c296347d8e9d2166b3c83eab97404c0670Paul Berry          * so that it comes after any global variable declarations
10901a851c296347d8e9d2166b3c83eab97404c0670Paul Berry          * that it refers to.
11060f898a90ebd29d2593866faa1f2d6f65961a414Ian Romanick	  */
11160f898a90ebd29d2593866faa1f2d6f65961a414Ian Romanick	 linked->symbols->add_function(f);
11201a851c296347d8e9d2166b3c83eab97404c0670Paul Berry	 linked->ir->push_tail(f);
11360f898a90ebd29d2593866faa1f2d6f65961a414Ian Romanick      }
114532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick
115532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      ir_function_signature *linked_sig =
1162619b1c96feed72444499021d8a870eab1c37e00Kenneth Graunke	 f->exact_matching_signature(&callee->parameters);
11766f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick      if ((linked_sig == NULL)
11866f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick	  || ((linked_sig != NULL)
11966f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick	      && (linked_sig->is_builtin != ir->use_builtin))) {
120532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick	 linked_sig = new(linked) ir_function_signature(callee->return_type);
121532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick	 f->add_signature(linked_sig);
122532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      }
123532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick
124532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      /* At this point linked_sig and called may be the same.  If ir is an
125532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * ir_call from linked then linked_sig and callee will be
126532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * ir_function_signatures that have no definitions (is_defined is false).
127532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       */
128532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      assert(!linked_sig->is_defined);
129532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      assert(linked_sig->body.is_empty());
130532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick
1318fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      /* Create an in-place clone of the function definition.  This multistep
1328fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       * process introduces some complexity here, but it has some advantages.
1338fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       * The parameter list and the and function body are cloned separately.
1348fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       * The clone of the parameter list is used to prime the hashtable used
1358fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       * to replace variable references in the cloned body.
1368fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       *
1378fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       * The big advantage is that the ir_function_signature does not change.
1388fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       * This means that we don't have to process the rest of the IR tree to
139532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * patch ir_call nodes.  In addition, there is no way to remove or
140532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * replace signature stored in a function.  One could easily be added,
141532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick       * but this avoids the need.
1428fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       */
1438fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      struct hash_table *ht = hash_table_ctor(0, hash_table_pointer_hash,
1448fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick					      hash_table_pointer_compare);
1458fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      exec_list formal_parameters;
1468fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      foreach_list_const(node, &sig->parameters) {
1478fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	 const ir_instruction *const original = (ir_instruction *) node;
1488fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	 assert(const_cast<ir_instruction *>(original)->as_variable());
1498fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
1508273bd46877e2ea2b8a02b87a11c68102d07e1f2Eric Anholt	 ir_instruction *copy = original->clone(linked, ht);
1518fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	 formal_parameters.push_tail(copy);
1528fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      }
1538fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
154532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      linked_sig->replace_parameters(&formal_parameters);
1558fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
1568fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      foreach_list_const(node, &sig->body) {
1578fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick	 const ir_instruction *const original = (ir_instruction *) node;
1588fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
1598273bd46877e2ea2b8a02b87a11c68102d07e1f2Eric Anholt	 ir_instruction *copy = original->clone(linked, ht);
160532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick	 linked_sig->body.push_tail(copy);
1618fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      }
1628fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
163532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick      linked_sig->is_defined = true;
164fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      hash_table_dtor(ht);
1658fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
166fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      /* Patch references inside the function to things outside the function
167fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick       * (i.e., function calls and global variables).
1688fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick       */
169fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      linked_sig->accept(this);
1708fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
17182065fa20ee3f2880a070f1f4f75509b910ceddeKenneth Graunke      ir->callee = linked_sig;
1725e5583ee06cff53db48151c13b21916a166ea2edEric Anholt
173fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      return visit_continue;
174fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   }
175fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick
176fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   virtual ir_visitor_status visit(ir_dereference_variable *ir)
177fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   {
178fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      if (hash_table_find(locals, ir->var) == NULL) {
179fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	 /* The non-function variable must be a global, so try to find the
180fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	  * variable in the shader's symbol table.  If the variable is not
181fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	  * found, then it's a global that *MUST* be defined in the original
182fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	  * shader.
183fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	  */
184fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	 ir_variable *var = linked->symbols->get_variable(ir->var->name);
185fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	 if (var == NULL) {
186fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	    /* Clone the ir_variable that the dereference already has and add
187fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	     * it to the linked shader.
188fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	     */
1898273bd46877e2ea2b8a02b87a11c68102d07e1f2Eric Anholt	    var = ir->var->clone(linked, NULL);
190001eee52d461233b1e1d6ed3577965e9bcb209e8Eric Anholt	    linked->symbols->add_variable(var);
191fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	    linked->ir->push_head(var);
1920f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	 } else if (var->type->is_array()) {
1930f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	    /* It is possible to have a global array declared in multiple
1940f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	     * shaders without a size.  The array is implicitly sized by the
1950f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	     * maximal access to it in *any* shader.  Because of this, we
1960f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	     * need to track the maximal access to the array as linking pulls
1970f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	     * more functions in that access the array.
1980f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	     */
1990f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	    var->max_array_access =
2000f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	       MAX2(var->max_array_access, ir->var->max_array_access);
2010f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick
2020f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	    if (var->type->length == 0 && ir->var->type->length != 0)
2030f4b2a0a23650d8f773c53d84cb2ead1f6d4fc8eIan Romanick	       var->type = ir->var->type;
204fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	 }
205fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick
206fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick	 ir->var = var;
207fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick      }
2088fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2098fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick      return visit_continue;
2108fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   }
2118fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2128fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   /** Was function linking successful? */
2138fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   bool success;
2148fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2158fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanickprivate:
2168fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   /**
2178fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick    * Shader program being linked
2188fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick    *
2198fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick    * This is only used for logging error messages.
2208fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick    */
2218fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   gl_shader_program *prog;
2228fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2238fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   /** List of shaders available for linking. */
2248fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   gl_shader **shader_list;
2258fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2268fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   /** Number of shaders available for linking. */
2278fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   unsigned num_shaders;
2288fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
229532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick   /**
230532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick    * Final linked shader
231532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick    *
232532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick    * This is used two ways.  It is used to find global variables in the
233532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick    * linked shader that are accessed by the function.  It is also used to add
234532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick    * global variables from the shader where the function originated.
235532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick    */
236532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick   gl_shader *linked;
237fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick
238fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   /**
239fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick    * Table of variables local to the function.
240fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick    */
241fc9ae101b4b7a71ca7a5d4f185e887064007e0d1Ian Romanick   hash_table *locals;
2425adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick};
2435adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick
2448fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2455adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick/**
2465adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick * Searches a list of shaders for a particular function definition
2475adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick */
2485adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanickir_function_signature *
2495adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanickfind_matching_signature(const char *name, const exec_list *actual_parameters,
25066f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick			gl_shader **shader_list, unsigned num_shaders,
25166f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick			bool use_builtin)
2525adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick{
2535adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick   for (unsigned i = 0; i < num_shaders; i++) {
2545adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick      ir_function *const f = shader_list[i]->symbols->get_function(name);
2558fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2565adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick      if (f == NULL)
2575adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick	 continue;
2588fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2595adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick      ir_function_signature *sig = f->matching_signature(actual_parameters);
2608fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2615adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick      if ((sig == NULL) || !sig->is_defined)
2625adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick	 continue;
2638fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
26466f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick      /* If this function expects to bind to a built-in function and the
26566f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick       * signature that we found isn't a built-in, keep looking.  Also keep
26666f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick       * looking if we expect a non-built-in but found a built-in.
26766f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick       */
26866f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick      if (use_builtin != sig->is_builtin)
26966f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick	    continue;
27066f4ac988d5053c9782d1390541b04f4d9c50078Ian Romanick
2715adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick      return sig;
2728fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   }
2735adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick
2745adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick   return NULL;
2755adbf0bff168c088d9fd5140226b76e3ba6471b8Ian Romanick}
2768fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2778fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2788fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanickbool
2798fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanicklink_function_calls(gl_shader_program *prog, gl_shader *main,
2808fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick		    gl_shader **shader_list, unsigned num_shaders)
2818fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick{
282532c2d30850908b75f4b0ad0aa5fa7ce88f8202dIan Romanick   call_link_visitor v(prog, main, shader_list, num_shaders);
2838fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick
2848fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   v.run(main->ir);
2858fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick   return v.success;
2868fe8a814b0c746f0f655a67f8755f9dee858d230Ian Romanick}
287