Clone of mesa.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

link_functions.cpp 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. /*
  2. * Copyright © 2010 Intel Corporation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice (including the next
  12. * paragraph) shall be included in all copies or substantial portions of the
  13. * Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  18. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21. * DEALINGS IN THE SOFTWARE.
  22. */
  23. #include "main/core.h"
  24. #include "glsl_symbol_table.h"
  25. #include "glsl_parser_extras.h"
  26. #include "ir.h"
  27. #include "program.h"
  28. #include "program/hash_table.h"
  29. #include "linker.h"
  30. static ir_function_signature *
  31. find_matching_signature(const char *name, const exec_list *actual_parameters,
  32. gl_shader **shader_list, unsigned num_shaders,
  33. bool use_builtin);
  34. class call_link_visitor : public ir_hierarchical_visitor {
  35. public:
  36. call_link_visitor(gl_shader_program *prog, gl_shader *linked,
  37. gl_shader **shader_list, unsigned num_shaders)
  38. {
  39. this->prog = prog;
  40. this->shader_list = shader_list;
  41. this->num_shaders = num_shaders;
  42. this->success = true;
  43. this->linked = linked;
  44. this->locals = hash_table_ctor(0, hash_table_pointer_hash,
  45. hash_table_pointer_compare);
  46. }
  47. ~call_link_visitor()
  48. {
  49. hash_table_dtor(this->locals);
  50. }
  51. virtual ir_visitor_status visit(ir_variable *ir)
  52. {
  53. hash_table_insert(locals, ir, ir);
  54. return visit_continue;
  55. }
  56. virtual ir_visitor_status visit_enter(ir_call *ir)
  57. {
  58. /* If ir is an ir_call from a function that was imported from another
  59. * shader callee will point to an ir_function_signature in the original
  60. * shader. In this case the function signature MUST NOT BE MODIFIED.
  61. * Doing so will modify the original shader. This may prevent that
  62. * shader from being linkable in other programs.
  63. */
  64. const ir_function_signature *const callee = ir->get_callee();
  65. assert(callee != NULL);
  66. const char *const name = callee->function_name();
  67. /* Determine if the requested function signature already exists in the
  68. * final linked shader. If it does, use it as the target of the call.
  69. */
  70. ir_function_signature *sig =
  71. find_matching_signature(name, &callee->parameters, &linked, 1,
  72. ir->use_builtin);
  73. if (sig != NULL) {
  74. ir->set_callee(sig);
  75. return visit_continue;
  76. }
  77. /* Try to find the signature in one of the other shaders that is being
  78. * linked. If it's not found there, return an error.
  79. */
  80. sig = find_matching_signature(name, &ir->actual_parameters, shader_list,
  81. num_shaders, ir->use_builtin);
  82. if (sig == NULL) {
  83. /* FINISHME: Log the full signature of unresolved function.
  84. */
  85. linker_error(this->prog, "unresolved reference to function `%s'\n",
  86. name);
  87. this->success = false;
  88. return visit_stop;
  89. }
  90. /* Find the prototype information in the linked shader. Generate any
  91. * details that may be missing.
  92. */
  93. ir_function *f = linked->symbols->get_function(name);
  94. if (f == NULL) {
  95. f = new(linked) ir_function(name);
  96. /* Add the new function to the linked IR.
  97. */
  98. linked->symbols->add_function(f);
  99. linked->ir->push_head(f);
  100. }
  101. ir_function_signature *linked_sig =
  102. f->exact_matching_signature(&callee->parameters);
  103. if ((linked_sig == NULL)
  104. || ((linked_sig != NULL)
  105. && (linked_sig->is_builtin != ir->use_builtin))) {
  106. linked_sig = new(linked) ir_function_signature(callee->return_type);
  107. f->add_signature(linked_sig);
  108. }
  109. /* At this point linked_sig and called may be the same. If ir is an
  110. * ir_call from linked then linked_sig and callee will be
  111. * ir_function_signatures that have no definitions (is_defined is false).
  112. */
  113. assert(!linked_sig->is_defined);
  114. assert(linked_sig->body.is_empty());
  115. /* Create an in-place clone of the function definition. This multistep
  116. * process introduces some complexity here, but it has some advantages.
  117. * The parameter list and the and function body are cloned separately.
  118. * The clone of the parameter list is used to prime the hashtable used
  119. * to replace variable references in the cloned body.
  120. *
  121. * The big advantage is that the ir_function_signature does not change.
  122. * This means that we don't have to process the rest of the IR tree to
  123. * patch ir_call nodes. In addition, there is no way to remove or
  124. * replace signature stored in a function. One could easily be added,
  125. * but this avoids the need.
  126. */
  127. struct hash_table *ht = hash_table_ctor(0, hash_table_pointer_hash,
  128. hash_table_pointer_compare);
  129. exec_list formal_parameters;
  130. foreach_list_const(node, &sig->parameters) {
  131. const ir_instruction *const original = (ir_instruction *) node;
  132. assert(const_cast<ir_instruction *>(original)->as_variable());
  133. ir_instruction *copy = original->clone(linked, ht);
  134. formal_parameters.push_tail(copy);
  135. }
  136. linked_sig->replace_parameters(&formal_parameters);
  137. foreach_list_const(node, &sig->body) {
  138. const ir_instruction *const original = (ir_instruction *) node;
  139. ir_instruction *copy = original->clone(linked, ht);
  140. linked_sig->body.push_tail(copy);
  141. }
  142. linked_sig->is_defined = true;
  143. hash_table_dtor(ht);
  144. /* Patch references inside the function to things outside the function
  145. * (i.e., function calls and global variables).
  146. */
  147. linked_sig->accept(this);
  148. ir->set_callee(linked_sig);
  149. return visit_continue;
  150. }
  151. virtual ir_visitor_status visit(ir_dereference_variable *ir)
  152. {
  153. if (hash_table_find(locals, ir->var) == NULL) {
  154. /* The non-function variable must be a global, so try to find the
  155. * variable in the shader's symbol table. If the variable is not
  156. * found, then it's a global that *MUST* be defined in the original
  157. * shader.
  158. */
  159. ir_variable *var = linked->symbols->get_variable(ir->var->name);
  160. if (var == NULL) {
  161. /* Clone the ir_variable that the dereference already has and add
  162. * it to the linked shader.
  163. */
  164. var = ir->var->clone(linked, NULL);
  165. linked->symbols->add_variable(var);
  166. linked->ir->push_head(var);
  167. } else if (var->type->is_array()) {
  168. /* It is possible to have a global array declared in multiple
  169. * shaders without a size. The array is implicitly sized by the
  170. * maximal access to it in *any* shader. Because of this, we
  171. * need to track the maximal access to the array as linking pulls
  172. * more functions in that access the array.
  173. */
  174. var->max_array_access =
  175. MAX2(var->max_array_access, ir->var->max_array_access);
  176. if (var->type->length == 0 && ir->var->type->length != 0)
  177. var->type = ir->var->type;
  178. }
  179. ir->var = var;
  180. }
  181. return visit_continue;
  182. }
  183. /** Was function linking successful? */
  184. bool success;
  185. private:
  186. /**
  187. * Shader program being linked
  188. *
  189. * This is only used for logging error messages.
  190. */
  191. gl_shader_program *prog;
  192. /** List of shaders available for linking. */
  193. gl_shader **shader_list;
  194. /** Number of shaders available for linking. */
  195. unsigned num_shaders;
  196. /**
  197. * Final linked shader
  198. *
  199. * This is used two ways. It is used to find global variables in the
  200. * linked shader that are accessed by the function. It is also used to add
  201. * global variables from the shader where the function originated.
  202. */
  203. gl_shader *linked;
  204. /**
  205. * Table of variables local to the function.
  206. */
  207. hash_table *locals;
  208. };
  209. /**
  210. * Searches a list of shaders for a particular function definition
  211. */
  212. ir_function_signature *
  213. find_matching_signature(const char *name, const exec_list *actual_parameters,
  214. gl_shader **shader_list, unsigned num_shaders,
  215. bool use_builtin)
  216. {
  217. for (unsigned i = 0; i < num_shaders; i++) {
  218. ir_function *const f = shader_list[i]->symbols->get_function(name);
  219. if (f == NULL)
  220. continue;
  221. ir_function_signature *sig = f->matching_signature(actual_parameters);
  222. if ((sig == NULL) || !sig->is_defined)
  223. continue;
  224. /* If this function expects to bind to a built-in function and the
  225. * signature that we found isn't a built-in, keep looking. Also keep
  226. * looking if we expect a non-built-in but found a built-in.
  227. */
  228. if (use_builtin != sig->is_builtin)
  229. continue;
  230. return sig;
  231. }
  232. return NULL;
  233. }
  234. bool
  235. link_function_calls(gl_shader_program *prog, gl_shader *main,
  236. gl_shader **shader_list, unsigned num_shaders)
  237. {
  238. call_link_visitor v(prog, main, shader_list, num_shaders);
  239. v.run(main->ir);
  240. return v.success;
  241. }