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 "glsl_types.h" 25 #include "ir.h" 26 27 typedef enum { 28 PARAMETER_LIST_NO_MATCH, 29 PARAMETER_LIST_EXACT_MATCH, 30 PARAMETER_LIST_INEXACT_MATCH /*< Match requires implicit conversion. */ 31 } parameter_list_match_t; 32 33 /** 34 * \brief Check if two parameter lists match. 35 * 36 * \param list_a Parameters of the function definition. 37 * \param list_b Actual parameters passed to the function. 38 * \see matching_signature() 39 */ 40 static parameter_list_match_t 41 parameter_lists_match(const exec_list *list_a, const exec_list *list_b) 42 { 43 const exec_node *node_a = list_a->head; 44 const exec_node *node_b = list_b->head; 45 46 /* This is set to true if there is an inexact match requiring an implicit 47 * conversion. */ 48 bool inexact_match = false; 49 50 for (/* empty */ 51 ; !node_a->is_tail_sentinel() 52 ; node_a = node_a->next, node_b = node_b->next) { 53 /* If all of the parameters from the other parameter list have been 54 * exhausted, the lists have different length and, by definition, 55 * do not match. 56 */ 57 if (node_b->is_tail_sentinel()) 58 return PARAMETER_LIST_NO_MATCH; 59 60 61 const ir_variable *const param = (ir_variable *) node_a; 62 const ir_rvalue *const actual = (ir_rvalue *) node_b; 63 64 if (param->type == actual->type) 65 continue; 66 67 /* Try to find an implicit conversion from actual to param. */ 68 inexact_match = true; 69 switch ((enum ir_variable_mode)(param->mode)) { 70 case ir_var_auto: 71 case ir_var_uniform: 72 case ir_var_temporary: 73 /* These are all error conditions. It is invalid for a parameter to 74 * a function to be declared as auto (not in, out, or inout) or 75 * as uniform. 76 */ 77 assert(0); 78 return PARAMETER_LIST_NO_MATCH; 79 80 case ir_var_const_in: 81 case ir_var_in: 82 if (!actual->type->can_implicitly_convert_to(param->type)) 83 return PARAMETER_LIST_NO_MATCH; 84 break; 85 86 case ir_var_out: 87 if (!param->type->can_implicitly_convert_to(actual->type)) 88 return PARAMETER_LIST_NO_MATCH; 89 break; 90 91 case ir_var_inout: 92 /* Since there are no bi-directional automatic conversions (e.g., 93 * there is int -> float but no float -> int), inout parameters must 94 * be exact matches. 95 */ 96 return PARAMETER_LIST_NO_MATCH; 97 98 default: 99 assert(false); 100 return PARAMETER_LIST_NO_MATCH; 101 } 102 } 103 104 /* If all of the parameters from the other parameter list have been 105 * exhausted, the lists have different length and, by definition, do not 106 * match. 107 */ 108 if (!node_b->is_tail_sentinel()) 109 return PARAMETER_LIST_NO_MATCH; 110 111 if (inexact_match) 112 return PARAMETER_LIST_INEXACT_MATCH; 113 else 114 return PARAMETER_LIST_EXACT_MATCH; 115 } 116 117 118 ir_function_signature * 119 ir_function::matching_signature(const exec_list *actual_parameters) 120 { 121 bool is_exact; 122 return matching_signature(actual_parameters, &is_exact); 123 } 124 125 ir_function_signature * 126 ir_function::matching_signature(const exec_list *actual_parameters, 127 bool *is_exact) 128 { 129 ir_function_signature *match = NULL; 130 bool multiple_inexact_matches = false; 131 132 /* From page 42 (page 49 of the PDF) of the GLSL 1.20 spec: 133 * 134 * "If an exact match is found, the other signatures are ignored, and 135 * the exact match is used. Otherwise, if no exact match is found, then 136 * the implicit conversions in Section 4.1.10 "Implicit Conversions" will 137 * be applied to the calling arguments if this can make their types match 138 * a signature. In this case, it is a semantic error if there are 139 * multiple ways to apply these conversions to the actual arguments of a 140 * call such that the call can be made to match multiple signatures." 141 */ 142 foreach_iter(exec_list_iterator, iter, signatures) { 143 ir_function_signature *const sig = 144 (ir_function_signature *) iter.get(); 145 146 switch (parameter_lists_match(& sig->parameters, actual_parameters)) { 147 case PARAMETER_LIST_EXACT_MATCH: 148 *is_exact = true; 149 return sig; 150 case PARAMETER_LIST_INEXACT_MATCH: 151 if (match == NULL) 152 match = sig; 153 else 154 multiple_inexact_matches = true; 155 continue; 156 case PARAMETER_LIST_NO_MATCH: 157 continue; 158 default: 159 assert(false); 160 return NULL; 161 } 162 } 163 164 /* There is no exact match (we would have returned it by now). If there 165 * are multiple inexact matches, the call is ambiguous, which is an error. 166 * 167 * FINISHME: Report a decent error. Returning NULL will likely result in 168 * FINISHME: a "no matching signature" error; it should report that the 169 * FINISHME: call is ambiguous. But reporting errors from here is hard. 170 */ 171 *is_exact = false; 172 173 if (multiple_inexact_matches) 174 return NULL; 175 176 return match; 177 } 178 179 180 static bool 181 parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b) 182 { 183 const exec_node *node_a = list_a->head; 184 const exec_node *node_b = list_b->head; 185 186 for (/* empty */ 187 ; !node_a->is_tail_sentinel() && !node_b->is_tail_sentinel() 188 ; node_a = node_a->next, node_b = node_b->next) { 189 ir_variable *a = (ir_variable *) node_a; 190 ir_variable *b = (ir_variable *) node_b; 191 192 /* If the types of the parameters do not match, the parameters lists 193 * are different. 194 */ 195 if (a->type != b->type) 196 return false; 197 } 198 199 /* Unless both lists are exhausted, they differ in length and, by 200 * definition, do not match. 201 */ 202 return (node_a->is_tail_sentinel() == node_b->is_tail_sentinel()); 203 } 204 205 ir_function_signature * 206 ir_function::exact_matching_signature(const exec_list *actual_parameters) 207 { 208 foreach_iter(exec_list_iterator, iter, signatures) { 209 ir_function_signature *const sig = 210 (ir_function_signature *) iter.get(); 211 212 if (parameter_lists_match_exact(&sig->parameters, actual_parameters)) 213 return sig; 214 } 215 return NULL; 216 } 217