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