link_functions.cpp revision 60f898a90ebd29d2593866faa1f2d6f65961a414
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 24#include "main/core.h" 25#include "glsl_symbol_table.h" 26#include "glsl_parser_extras.h" 27#include "ir.h" 28#include "program.h" 29#include "program/hash_table.h" 30#include "linker.h" 31 32static ir_function_signature * 33find_matching_signature(const char *name, const exec_list *actual_parameters, 34 gl_shader **shader_list, unsigned num_shaders); 35 36class call_link_visitor : public ir_hierarchical_visitor { 37public: 38 call_link_visitor(gl_shader_program *prog, gl_shader *linked, 39 gl_shader **shader_list, unsigned num_shaders) 40 { 41 this->prog = prog; 42 this->shader_list = shader_list; 43 this->num_shaders = num_shaders; 44 this->success = true; 45 this->linked = linked; 46 47 this->locals = hash_table_ctor(0, hash_table_pointer_hash, 48 hash_table_pointer_compare); 49 } 50 51 ~call_link_visitor() 52 { 53 hash_table_dtor(this->locals); 54 } 55 56 virtual ir_visitor_status visit(ir_variable *ir) 57 { 58 hash_table_insert(locals, ir, ir); 59 return visit_continue; 60 } 61 62 virtual ir_visitor_status visit_enter(ir_call *ir) 63 { 64 /* If ir is an ir_call from a function that was imported from another 65 * shader callee will point to an ir_function_signature in the original 66 * shader. In this case the function signature MUST NOT BE MODIFIED. 67 * Doing so will modify the original shader. This may prevent that 68 * shader from being linkable in other programs. 69 */ 70 const ir_function_signature *const callee = ir->get_callee(); 71 assert(callee != NULL); 72 const char *const name = callee->function_name(); 73 74 /* Determine if the requested function signature already exists in the 75 * final linked shader. If it does, use it as the target of the call. 76 */ 77 ir_function_signature *sig = 78 find_matching_signature(name, &callee->parameters, &linked, 1); 79 if (sig != NULL) { 80 ir->set_callee(sig); 81 return visit_continue; 82 } 83 84 /* Try to find the signature in one of the other shaders that is being 85 * linked. If it's not found there, return an error. 86 */ 87 sig = find_matching_signature(name, &ir->actual_parameters, shader_list, 88 num_shaders); 89 if (sig == NULL) { 90 /* FINISHME: Log the full signature of unresolved function. 91 */ 92 linker_error_printf(this->prog, "unresolved reference to function " 93 "`%s'\n", name); 94 this->success = false; 95 return visit_stop; 96 } 97 98 /* Find the prototype information in the linked shader. Generate any 99 * details that may be missing. 100 */ 101 ir_function *f = linked->symbols->get_function(name); 102 if (f == NULL) { 103 f = new(linked) ir_function(name); 104 105 /* Add the new function to the linked IR. 106 */ 107 linked->symbols->add_function(f); 108 linked->ir->push_head(f); 109 } 110 111 ir_function_signature *linked_sig = 112 f->exact_matching_signature(&callee->parameters); 113 if (linked_sig == NULL) { 114 linked_sig = new(linked) ir_function_signature(callee->return_type); 115 f->add_signature(linked_sig); 116 } 117 118 /* At this point linked_sig and called may be the same. If ir is an 119 * ir_call from linked then linked_sig and callee will be 120 * ir_function_signatures that have no definitions (is_defined is false). 121 */ 122 assert(!linked_sig->is_defined); 123 assert(linked_sig->body.is_empty()); 124 125 /* Create an in-place clone of the function definition. This multistep 126 * process introduces some complexity here, but it has some advantages. 127 * The parameter list and the and function body are cloned separately. 128 * The clone of the parameter list is used to prime the hashtable used 129 * to replace variable references in the cloned body. 130 * 131 * The big advantage is that the ir_function_signature does not change. 132 * This means that we don't have to process the rest of the IR tree to 133 * patch ir_call nodes. In addition, there is no way to remove or 134 * replace signature stored in a function. One could easily be added, 135 * but this avoids the need. 136 */ 137 struct hash_table *ht = hash_table_ctor(0, hash_table_pointer_hash, 138 hash_table_pointer_compare); 139 exec_list formal_parameters; 140 foreach_list_const(node, &sig->parameters) { 141 const ir_instruction *const original = (ir_instruction *) node; 142 assert(const_cast<ir_instruction *>(original)->as_variable()); 143 144 ir_instruction *copy = original->clone(linked, ht); 145 formal_parameters.push_tail(copy); 146 } 147 148 linked_sig->replace_parameters(&formal_parameters); 149 150 foreach_list_const(node, &sig->body) { 151 const ir_instruction *const original = (ir_instruction *) node; 152 153 ir_instruction *copy = original->clone(linked, ht); 154 linked_sig->body.push_tail(copy); 155 } 156 157 linked_sig->is_defined = true; 158 hash_table_dtor(ht); 159 160 /* Patch references inside the function to things outside the function 161 * (i.e., function calls and global variables). 162 */ 163 linked_sig->accept(this); 164 165 ir->set_callee(linked_sig); 166 167 return visit_continue; 168 } 169 170 virtual ir_visitor_status visit(ir_dereference_variable *ir) 171 { 172 if (hash_table_find(locals, ir->var) == NULL) { 173 /* The non-function variable must be a global, so try to find the 174 * variable in the shader's symbol table. If the variable is not 175 * found, then it's a global that *MUST* be defined in the original 176 * shader. 177 */ 178 ir_variable *var = linked->symbols->get_variable(ir->var->name); 179 if (var == NULL) { 180 /* Clone the ir_variable that the dereference already has and add 181 * it to the linked shader. 182 */ 183 var = ir->var->clone(linked, NULL); 184 linked->symbols->add_variable(var); 185 linked->ir->push_head(var); 186 } else if (var->type->is_array()) { 187 /* It is possible to have a global array declared in multiple 188 * shaders without a size. The array is implicitly sized by the 189 * maximal access to it in *any* shader. Because of this, we 190 * need to track the maximal access to the array as linking pulls 191 * more functions in that access the array. 192 */ 193 var->max_array_access = 194 MAX2(var->max_array_access, ir->var->max_array_access); 195 196 if (var->type->length == 0 && ir->var->type->length != 0) 197 var->type = ir->var->type; 198 } 199 200 ir->var = var; 201 } 202 203 return visit_continue; 204 } 205 206 /** Was function linking successful? */ 207 bool success; 208 209private: 210 /** 211 * Shader program being linked 212 * 213 * This is only used for logging error messages. 214 */ 215 gl_shader_program *prog; 216 217 /** List of shaders available for linking. */ 218 gl_shader **shader_list; 219 220 /** Number of shaders available for linking. */ 221 unsigned num_shaders; 222 223 /** 224 * Final linked shader 225 * 226 * This is used two ways. It is used to find global variables in the 227 * linked shader that are accessed by the function. It is also used to add 228 * global variables from the shader where the function originated. 229 */ 230 gl_shader *linked; 231 232 /** 233 * Table of variables local to the function. 234 */ 235 hash_table *locals; 236}; 237 238 239/** 240 * Searches a list of shaders for a particular function definition 241 */ 242ir_function_signature * 243find_matching_signature(const char *name, const exec_list *actual_parameters, 244 gl_shader **shader_list, unsigned num_shaders) 245{ 246 for (unsigned i = 0; i < num_shaders; i++) { 247 ir_function *const f = shader_list[i]->symbols->get_function(name); 248 249 if (f == NULL) 250 continue; 251 252 ir_function_signature *sig = f->matching_signature(actual_parameters); 253 254 if ((sig == NULL) || !sig->is_defined) 255 continue; 256 257 return sig; 258 } 259 260 return NULL; 261} 262 263 264bool 265link_function_calls(gl_shader_program *prog, gl_shader *main, 266 gl_shader **shader_list, unsigned num_shaders) 267{ 268 call_link_visitor v(prog, main, shader_list, num_shaders); 269 270 v.run(main->ir); 271 return v.success; 272} 273