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