1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2010 Intel Corporation
3*61046927SAndroid Build Coastguard Worker *
4*61046927SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
5*61046927SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
6*61046927SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
7*61046927SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*61046927SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
9*61046927SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker *
11*61046927SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker * Software.
14*61046927SAndroid Build Coastguard Worker *
15*61046927SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18*61046927SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*61046927SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*61046927SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
22*61046927SAndroid Build Coastguard Worker */
23*61046927SAndroid Build Coastguard Worker
24*61046927SAndroid Build Coastguard Worker #include "compiler/glsl_types.h"
25*61046927SAndroid Build Coastguard Worker #include "ir.h"
26*61046927SAndroid Build Coastguard Worker #include "glsl_parser_extras.h"
27*61046927SAndroid Build Coastguard Worker #include "main/errors.h"
28*61046927SAndroid Build Coastguard Worker
29*61046927SAndroid Build Coastguard Worker typedef enum {
30*61046927SAndroid Build Coastguard Worker PARAMETER_LIST_NO_MATCH,
31*61046927SAndroid Build Coastguard Worker PARAMETER_LIST_EXACT_MATCH,
32*61046927SAndroid Build Coastguard Worker PARAMETER_LIST_INEXACT_MATCH /*< Match requires implicit conversion. */
33*61046927SAndroid Build Coastguard Worker } parameter_list_match_t;
34*61046927SAndroid Build Coastguard Worker
35*61046927SAndroid Build Coastguard Worker static inline const glsl_type *
get_param_type(const ir_instruction * inst)36*61046927SAndroid Build Coastguard Worker get_param_type(const ir_instruction *inst)
37*61046927SAndroid Build Coastguard Worker {
38*61046927SAndroid Build Coastguard Worker const ir_variable *var = inst->as_variable();
39*61046927SAndroid Build Coastguard Worker if (var)
40*61046927SAndroid Build Coastguard Worker return var->type;
41*61046927SAndroid Build Coastguard Worker
42*61046927SAndroid Build Coastguard Worker const ir_rvalue *rvalue = inst->as_rvalue();
43*61046927SAndroid Build Coastguard Worker assert(rvalue != NULL);
44*61046927SAndroid Build Coastguard Worker return rvalue->type;
45*61046927SAndroid Build Coastguard Worker }
46*61046927SAndroid Build Coastguard Worker
47*61046927SAndroid Build Coastguard Worker /**
48*61046927SAndroid Build Coastguard Worker * \brief Check if two parameter lists match.
49*61046927SAndroid Build Coastguard Worker *
50*61046927SAndroid Build Coastguard Worker * \param list_a Parameters of the function definition.
51*61046927SAndroid Build Coastguard Worker * \param list_b Actual parameters passed to the function.
52*61046927SAndroid Build Coastguard Worker * \see matching_signature()
53*61046927SAndroid Build Coastguard Worker */
54*61046927SAndroid Build Coastguard Worker static parameter_list_match_t
parameter_lists_match(bool has_implicit_conversions,bool has_implicit_int_to_uint_conversion,const exec_list * list_a,const exec_list * list_b)55*61046927SAndroid Build Coastguard Worker parameter_lists_match(bool has_implicit_conversions,
56*61046927SAndroid Build Coastguard Worker bool has_implicit_int_to_uint_conversion,
57*61046927SAndroid Build Coastguard Worker const exec_list *list_a, const exec_list *list_b)
58*61046927SAndroid Build Coastguard Worker {
59*61046927SAndroid Build Coastguard Worker const exec_node *node_a = list_a->get_head_raw();
60*61046927SAndroid Build Coastguard Worker const exec_node *node_b = list_b->get_head_raw();
61*61046927SAndroid Build Coastguard Worker
62*61046927SAndroid Build Coastguard Worker /* This is set to true if there is an inexact match requiring an implicit
63*61046927SAndroid Build Coastguard Worker * conversion. */
64*61046927SAndroid Build Coastguard Worker bool inexact_match = false;
65*61046927SAndroid Build Coastguard Worker
66*61046927SAndroid Build Coastguard Worker for (/* empty */
67*61046927SAndroid Build Coastguard Worker ; !node_a->is_tail_sentinel()
68*61046927SAndroid Build Coastguard Worker ; node_a = node_a->next, node_b = node_b->next) {
69*61046927SAndroid Build Coastguard Worker /* If all of the parameters from the other parameter list have been
70*61046927SAndroid Build Coastguard Worker * exhausted, the lists have different length and, by definition,
71*61046927SAndroid Build Coastguard Worker * do not match.
72*61046927SAndroid Build Coastguard Worker */
73*61046927SAndroid Build Coastguard Worker if (node_b->is_tail_sentinel())
74*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_NO_MATCH;
75*61046927SAndroid Build Coastguard Worker
76*61046927SAndroid Build Coastguard Worker const ir_instruction *inst_a = (const ir_instruction *) node_a;
77*61046927SAndroid Build Coastguard Worker const ir_instruction *inst_b = (const ir_instruction *) node_b;
78*61046927SAndroid Build Coastguard Worker
79*61046927SAndroid Build Coastguard Worker const ir_variable *const param = inst_a->as_variable();
80*61046927SAndroid Build Coastguard Worker assert(param != NULL);
81*61046927SAndroid Build Coastguard Worker const glsl_type *actual_type = get_param_type(inst_b);
82*61046927SAndroid Build Coastguard Worker
83*61046927SAndroid Build Coastguard Worker if (param->type == actual_type)
84*61046927SAndroid Build Coastguard Worker continue;
85*61046927SAndroid Build Coastguard Worker
86*61046927SAndroid Build Coastguard Worker /* Try to find an implicit conversion from actual to param. */
87*61046927SAndroid Build Coastguard Worker inexact_match = true;
88*61046927SAndroid Build Coastguard Worker switch ((enum ir_variable_mode)(param->data.mode)) {
89*61046927SAndroid Build Coastguard Worker case ir_var_auto:
90*61046927SAndroid Build Coastguard Worker case ir_var_uniform:
91*61046927SAndroid Build Coastguard Worker case ir_var_shader_storage:
92*61046927SAndroid Build Coastguard Worker case ir_var_temporary:
93*61046927SAndroid Build Coastguard Worker /* These are all error conditions. It is invalid for a parameter to
94*61046927SAndroid Build Coastguard Worker * a function to be declared as auto (not in, out, or inout) or
95*61046927SAndroid Build Coastguard Worker * as uniform.
96*61046927SAndroid Build Coastguard Worker */
97*61046927SAndroid Build Coastguard Worker assert(0);
98*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_NO_MATCH;
99*61046927SAndroid Build Coastguard Worker
100*61046927SAndroid Build Coastguard Worker case ir_var_const_in:
101*61046927SAndroid Build Coastguard Worker case ir_var_function_in:
102*61046927SAndroid Build Coastguard Worker if (param->data.implicit_conversion_prohibited ||
103*61046927SAndroid Build Coastguard Worker !_mesa_glsl_can_implicitly_convert(actual_type, param->type,
104*61046927SAndroid Build Coastguard Worker has_implicit_conversions,
105*61046927SAndroid Build Coastguard Worker has_implicit_int_to_uint_conversion))
106*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_NO_MATCH;
107*61046927SAndroid Build Coastguard Worker break;
108*61046927SAndroid Build Coastguard Worker
109*61046927SAndroid Build Coastguard Worker case ir_var_function_out:
110*61046927SAndroid Build Coastguard Worker if (!_mesa_glsl_can_implicitly_convert(param->type, actual_type,
111*61046927SAndroid Build Coastguard Worker has_implicit_conversions,
112*61046927SAndroid Build Coastguard Worker has_implicit_int_to_uint_conversion))
113*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_NO_MATCH;
114*61046927SAndroid Build Coastguard Worker break;
115*61046927SAndroid Build Coastguard Worker
116*61046927SAndroid Build Coastguard Worker case ir_var_function_inout:
117*61046927SAndroid Build Coastguard Worker /* Since there are no bi-directional automatic conversions (e.g.,
118*61046927SAndroid Build Coastguard Worker * there is int -> float but no float -> int), inout parameters must
119*61046927SAndroid Build Coastguard Worker * be exact matches.
120*61046927SAndroid Build Coastguard Worker */
121*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_NO_MATCH;
122*61046927SAndroid Build Coastguard Worker
123*61046927SAndroid Build Coastguard Worker default:
124*61046927SAndroid Build Coastguard Worker assert(false);
125*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_NO_MATCH;
126*61046927SAndroid Build Coastguard Worker }
127*61046927SAndroid Build Coastguard Worker }
128*61046927SAndroid Build Coastguard Worker
129*61046927SAndroid Build Coastguard Worker /* If all of the parameters from the other parameter list have been
130*61046927SAndroid Build Coastguard Worker * exhausted, the lists have different length and, by definition, do not
131*61046927SAndroid Build Coastguard Worker * match.
132*61046927SAndroid Build Coastguard Worker */
133*61046927SAndroid Build Coastguard Worker if (!node_b->is_tail_sentinel())
134*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_NO_MATCH;
135*61046927SAndroid Build Coastguard Worker
136*61046927SAndroid Build Coastguard Worker if (inexact_match)
137*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_INEXACT_MATCH;
138*61046927SAndroid Build Coastguard Worker else
139*61046927SAndroid Build Coastguard Worker return PARAMETER_LIST_EXACT_MATCH;
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard Worker
143*61046927SAndroid Build Coastguard Worker /* Classes of parameter match, sorted (mostly) best matches first.
144*61046927SAndroid Build Coastguard Worker * See is_better_parameter_match() below for the exceptions.
145*61046927SAndroid Build Coastguard Worker * */
146*61046927SAndroid Build Coastguard Worker typedef enum {
147*61046927SAndroid Build Coastguard Worker PARAMETER_EXACT_MATCH,
148*61046927SAndroid Build Coastguard Worker PARAMETER_FLOAT_TO_DOUBLE,
149*61046927SAndroid Build Coastguard Worker PARAMETER_INT_TO_FLOAT,
150*61046927SAndroid Build Coastguard Worker PARAMETER_INT_TO_DOUBLE,
151*61046927SAndroid Build Coastguard Worker PARAMETER_OTHER_CONVERSION,
152*61046927SAndroid Build Coastguard Worker } parameter_match_t;
153*61046927SAndroid Build Coastguard Worker
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker static parameter_match_t
get_parameter_match_type(const ir_variable * param,const ir_rvalue * actual)156*61046927SAndroid Build Coastguard Worker get_parameter_match_type(const ir_variable *param,
157*61046927SAndroid Build Coastguard Worker const ir_rvalue *actual)
158*61046927SAndroid Build Coastguard Worker {
159*61046927SAndroid Build Coastguard Worker const glsl_type *from_type;
160*61046927SAndroid Build Coastguard Worker const glsl_type *to_type;
161*61046927SAndroid Build Coastguard Worker
162*61046927SAndroid Build Coastguard Worker if (param->data.mode == ir_var_function_out) {
163*61046927SAndroid Build Coastguard Worker from_type = param->type;
164*61046927SAndroid Build Coastguard Worker to_type = actual->type;
165*61046927SAndroid Build Coastguard Worker } else {
166*61046927SAndroid Build Coastguard Worker from_type = actual->type;
167*61046927SAndroid Build Coastguard Worker to_type = param->type;
168*61046927SAndroid Build Coastguard Worker }
169*61046927SAndroid Build Coastguard Worker
170*61046927SAndroid Build Coastguard Worker if (from_type == to_type)
171*61046927SAndroid Build Coastguard Worker return PARAMETER_EXACT_MATCH;
172*61046927SAndroid Build Coastguard Worker
173*61046927SAndroid Build Coastguard Worker if (glsl_type_is_double(to_type)) {
174*61046927SAndroid Build Coastguard Worker if (glsl_type_is_float(from_type))
175*61046927SAndroid Build Coastguard Worker return PARAMETER_FLOAT_TO_DOUBLE;
176*61046927SAndroid Build Coastguard Worker return PARAMETER_INT_TO_DOUBLE;
177*61046927SAndroid Build Coastguard Worker }
178*61046927SAndroid Build Coastguard Worker
179*61046927SAndroid Build Coastguard Worker if (glsl_type_is_float(to_type))
180*61046927SAndroid Build Coastguard Worker return PARAMETER_INT_TO_FLOAT;
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker /* int -> uint and any other oddball conversions */
183*61046927SAndroid Build Coastguard Worker return PARAMETER_OTHER_CONVERSION;
184*61046927SAndroid Build Coastguard Worker }
185*61046927SAndroid Build Coastguard Worker
186*61046927SAndroid Build Coastguard Worker
187*61046927SAndroid Build Coastguard Worker static bool
is_better_parameter_match(parameter_match_t a_match,parameter_match_t b_match)188*61046927SAndroid Build Coastguard Worker is_better_parameter_match(parameter_match_t a_match,
189*61046927SAndroid Build Coastguard Worker parameter_match_t b_match)
190*61046927SAndroid Build Coastguard Worker {
191*61046927SAndroid Build Coastguard Worker /* From section 6.1 of the GLSL 4.00 spec (and the ARB_gpu_shader5 spec):
192*61046927SAndroid Build Coastguard Worker *
193*61046927SAndroid Build Coastguard Worker * 1. An exact match is better than a match involving any implicit
194*61046927SAndroid Build Coastguard Worker * conversion.
195*61046927SAndroid Build Coastguard Worker *
196*61046927SAndroid Build Coastguard Worker * 2. A match involving an implicit conversion from float to double
197*61046927SAndroid Build Coastguard Worker * is better than match involving any other implicit conversion.
198*61046927SAndroid Build Coastguard Worker *
199*61046927SAndroid Build Coastguard Worker * [XXX: Not in GLSL 4.0: Only in ARB_gpu_shader5:
200*61046927SAndroid Build Coastguard Worker * 3. A match involving an implicit conversion from either int or uint
201*61046927SAndroid Build Coastguard Worker * to float is better than a match involving an implicit conversion
202*61046927SAndroid Build Coastguard Worker * from either int or uint to double.]
203*61046927SAndroid Build Coastguard Worker *
204*61046927SAndroid Build Coastguard Worker * If none of the rules above apply to a particular pair of conversions,
205*61046927SAndroid Build Coastguard Worker * neither conversion is considered better than the other.
206*61046927SAndroid Build Coastguard Worker *
207*61046927SAndroid Build Coastguard Worker * --
208*61046927SAndroid Build Coastguard Worker *
209*61046927SAndroid Build Coastguard Worker * Notably, the int->uint conversion is *not* considered to be better
210*61046927SAndroid Build Coastguard Worker * or worse than int/uint->float or int/uint->double.
211*61046927SAndroid Build Coastguard Worker */
212*61046927SAndroid Build Coastguard Worker
213*61046927SAndroid Build Coastguard Worker if (a_match >= PARAMETER_INT_TO_FLOAT && b_match == PARAMETER_OTHER_CONVERSION)
214*61046927SAndroid Build Coastguard Worker return false;
215*61046927SAndroid Build Coastguard Worker
216*61046927SAndroid Build Coastguard Worker return a_match < b_match;
217*61046927SAndroid Build Coastguard Worker }
218*61046927SAndroid Build Coastguard Worker
219*61046927SAndroid Build Coastguard Worker
220*61046927SAndroid Build Coastguard Worker static bool
is_best_inexact_overload(const exec_list * actual_parameters,ir_function_signature ** matches,int num_matches,ir_function_signature * sig)221*61046927SAndroid Build Coastguard Worker is_best_inexact_overload(const exec_list *actual_parameters,
222*61046927SAndroid Build Coastguard Worker ir_function_signature **matches,
223*61046927SAndroid Build Coastguard Worker int num_matches,
224*61046927SAndroid Build Coastguard Worker ir_function_signature *sig)
225*61046927SAndroid Build Coastguard Worker {
226*61046927SAndroid Build Coastguard Worker /* From section 6.1 of the GLSL 4.00 spec (and the ARB_gpu_shader5 spec):
227*61046927SAndroid Build Coastguard Worker *
228*61046927SAndroid Build Coastguard Worker * "A function definition A is considered a better
229*61046927SAndroid Build Coastguard Worker * match than function definition B if:
230*61046927SAndroid Build Coastguard Worker *
231*61046927SAndroid Build Coastguard Worker * * for at least one function argument, the conversion for that argument
232*61046927SAndroid Build Coastguard Worker * in A is better than the corresponding conversion in B; and
233*61046927SAndroid Build Coastguard Worker *
234*61046927SAndroid Build Coastguard Worker * * there is no function argument for which the conversion in B is better
235*61046927SAndroid Build Coastguard Worker * than the corresponding conversion in A.
236*61046927SAndroid Build Coastguard Worker *
237*61046927SAndroid Build Coastguard Worker * If a single function definition is considered a better match than every
238*61046927SAndroid Build Coastguard Worker * other matching function definition, it will be used. Otherwise, a
239*61046927SAndroid Build Coastguard Worker * semantic error occurs and the shader will fail to compile."
240*61046927SAndroid Build Coastguard Worker */
241*61046927SAndroid Build Coastguard Worker for (ir_function_signature **other = matches;
242*61046927SAndroid Build Coastguard Worker other < matches + num_matches; other++) {
243*61046927SAndroid Build Coastguard Worker if (*other == sig)
244*61046927SAndroid Build Coastguard Worker continue;
245*61046927SAndroid Build Coastguard Worker
246*61046927SAndroid Build Coastguard Worker const exec_node *node_a = sig->parameters.get_head_raw();
247*61046927SAndroid Build Coastguard Worker const exec_node *node_b = (*other)->parameters.get_head_raw();
248*61046927SAndroid Build Coastguard Worker const exec_node *node_p = actual_parameters->get_head_raw();
249*61046927SAndroid Build Coastguard Worker
250*61046927SAndroid Build Coastguard Worker bool better_for_some_parameter = false;
251*61046927SAndroid Build Coastguard Worker
252*61046927SAndroid Build Coastguard Worker for (/* empty */
253*61046927SAndroid Build Coastguard Worker ; !node_a->is_tail_sentinel()
254*61046927SAndroid Build Coastguard Worker ; node_a = node_a->next,
255*61046927SAndroid Build Coastguard Worker node_b = node_b->next,
256*61046927SAndroid Build Coastguard Worker node_p = node_p->next) {
257*61046927SAndroid Build Coastguard Worker parameter_match_t a_match = get_parameter_match_type(
258*61046927SAndroid Build Coastguard Worker (const ir_variable *)node_a,
259*61046927SAndroid Build Coastguard Worker (const ir_rvalue *)node_p);
260*61046927SAndroid Build Coastguard Worker parameter_match_t b_match = get_parameter_match_type(
261*61046927SAndroid Build Coastguard Worker (const ir_variable *)node_b,
262*61046927SAndroid Build Coastguard Worker (const ir_rvalue *)node_p);
263*61046927SAndroid Build Coastguard Worker
264*61046927SAndroid Build Coastguard Worker if (is_better_parameter_match(a_match, b_match))
265*61046927SAndroid Build Coastguard Worker better_for_some_parameter = true;
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker if (is_better_parameter_match(b_match, a_match))
268*61046927SAndroid Build Coastguard Worker return false; /* B is better for this parameter */
269*61046927SAndroid Build Coastguard Worker }
270*61046927SAndroid Build Coastguard Worker
271*61046927SAndroid Build Coastguard Worker if (!better_for_some_parameter)
272*61046927SAndroid Build Coastguard Worker return false; /* A must be better than B for some parameter */
273*61046927SAndroid Build Coastguard Worker
274*61046927SAndroid Build Coastguard Worker }
275*61046927SAndroid Build Coastguard Worker
276*61046927SAndroid Build Coastguard Worker return true;
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker static ir_function_signature *
choose_best_inexact_overload(_mesa_glsl_parse_state * state,const exec_list * actual_parameters,ir_function_signature ** matches,int num_matches,bool has_choose_best_inexact_overload)281*61046927SAndroid Build Coastguard Worker choose_best_inexact_overload(_mesa_glsl_parse_state *state,
282*61046927SAndroid Build Coastguard Worker const exec_list *actual_parameters,
283*61046927SAndroid Build Coastguard Worker ir_function_signature **matches, int num_matches,
284*61046927SAndroid Build Coastguard Worker bool has_choose_best_inexact_overload)
285*61046927SAndroid Build Coastguard Worker {
286*61046927SAndroid Build Coastguard Worker if (num_matches == 0)
287*61046927SAndroid Build Coastguard Worker return NULL;
288*61046927SAndroid Build Coastguard Worker
289*61046927SAndroid Build Coastguard Worker if (num_matches == 1)
290*61046927SAndroid Build Coastguard Worker return *matches;
291*61046927SAndroid Build Coastguard Worker
292*61046927SAndroid Build Coastguard Worker if (has_choose_best_inexact_overload) {
293*61046927SAndroid Build Coastguard Worker for (ir_function_signature **sig = matches; sig < matches + num_matches; sig++) {
294*61046927SAndroid Build Coastguard Worker if (is_best_inexact_overload(actual_parameters, matches, num_matches, *sig))
295*61046927SAndroid Build Coastguard Worker return *sig;
296*61046927SAndroid Build Coastguard Worker }
297*61046927SAndroid Build Coastguard Worker }
298*61046927SAndroid Build Coastguard Worker
299*61046927SAndroid Build Coastguard Worker return NULL; /* no best candidate */
300*61046927SAndroid Build Coastguard Worker }
301*61046927SAndroid Build Coastguard Worker
302*61046927SAndroid Build Coastguard Worker
303*61046927SAndroid Build Coastguard Worker ir_function_signature *
matching_signature(_mesa_glsl_parse_state * state,const exec_list * actual_parameters,bool has_implicit_conversions,bool has_implicit_int_to_uint_conversion,bool allow_builtins)304*61046927SAndroid Build Coastguard Worker ir_function::matching_signature(_mesa_glsl_parse_state *state,
305*61046927SAndroid Build Coastguard Worker const exec_list *actual_parameters,
306*61046927SAndroid Build Coastguard Worker bool has_implicit_conversions,
307*61046927SAndroid Build Coastguard Worker bool has_implicit_int_to_uint_conversion,
308*61046927SAndroid Build Coastguard Worker bool allow_builtins)
309*61046927SAndroid Build Coastguard Worker {
310*61046927SAndroid Build Coastguard Worker bool is_exact;
311*61046927SAndroid Build Coastguard Worker return matching_signature(state, actual_parameters, has_implicit_conversions,
312*61046927SAndroid Build Coastguard Worker has_implicit_int_to_uint_conversion,
313*61046927SAndroid Build Coastguard Worker allow_builtins, &is_exact);
314*61046927SAndroid Build Coastguard Worker }
315*61046927SAndroid Build Coastguard Worker
316*61046927SAndroid Build Coastguard Worker ir_function_signature *
matching_signature(_mesa_glsl_parse_state * state,const exec_list * actual_parameters,bool has_implicit_conversions,bool has_implicit_int_to_uint_conversion,bool allow_builtins,bool * is_exact)317*61046927SAndroid Build Coastguard Worker ir_function::matching_signature(_mesa_glsl_parse_state *state,
318*61046927SAndroid Build Coastguard Worker const exec_list *actual_parameters,
319*61046927SAndroid Build Coastguard Worker bool has_implicit_conversions,
320*61046927SAndroid Build Coastguard Worker bool has_implicit_int_to_uint_conversion,
321*61046927SAndroid Build Coastguard Worker bool allow_builtins,
322*61046927SAndroid Build Coastguard Worker bool *is_exact)
323*61046927SAndroid Build Coastguard Worker {
324*61046927SAndroid Build Coastguard Worker ir_function_signature **inexact_matches = NULL;
325*61046927SAndroid Build Coastguard Worker ir_function_signature **inexact_matches_temp;
326*61046927SAndroid Build Coastguard Worker ir_function_signature *match = NULL;
327*61046927SAndroid Build Coastguard Worker int num_inexact_matches = 0;
328*61046927SAndroid Build Coastguard Worker
329*61046927SAndroid Build Coastguard Worker /* From page 42 (page 49 of the PDF) of the GLSL 1.20 spec:
330*61046927SAndroid Build Coastguard Worker *
331*61046927SAndroid Build Coastguard Worker * "If an exact match is found, the other signatures are ignored, and
332*61046927SAndroid Build Coastguard Worker * the exact match is used. Otherwise, if no exact match is found, then
333*61046927SAndroid Build Coastguard Worker * the implicit conversions in Section 4.1.10 "Implicit Conversions" will
334*61046927SAndroid Build Coastguard Worker * be applied to the calling arguments if this can make their types match
335*61046927SAndroid Build Coastguard Worker * a signature. In this case, it is a semantic error if there are
336*61046927SAndroid Build Coastguard Worker * multiple ways to apply these conversions to the actual arguments of a
337*61046927SAndroid Build Coastguard Worker * call such that the call can be made to match multiple signatures."
338*61046927SAndroid Build Coastguard Worker */
339*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_function_signature, sig, &this->signatures) {
340*61046927SAndroid Build Coastguard Worker /* Skip over any built-ins that aren't available in this shader. */
341*61046927SAndroid Build Coastguard Worker if (sig->is_builtin() && (!allow_builtins ||
342*61046927SAndroid Build Coastguard Worker !sig->is_builtin_available(state)))
343*61046927SAndroid Build Coastguard Worker continue;
344*61046927SAndroid Build Coastguard Worker
345*61046927SAndroid Build Coastguard Worker switch (parameter_lists_match(has_implicit_conversions,
346*61046927SAndroid Build Coastguard Worker has_implicit_int_to_uint_conversion,
347*61046927SAndroid Build Coastguard Worker &sig->parameters, actual_parameters)) {
348*61046927SAndroid Build Coastguard Worker case PARAMETER_LIST_EXACT_MATCH:
349*61046927SAndroid Build Coastguard Worker *is_exact = true;
350*61046927SAndroid Build Coastguard Worker free(inexact_matches);
351*61046927SAndroid Build Coastguard Worker return sig;
352*61046927SAndroid Build Coastguard Worker case PARAMETER_LIST_INEXACT_MATCH:
353*61046927SAndroid Build Coastguard Worker /* Subroutine signatures must match exactly */
354*61046927SAndroid Build Coastguard Worker if (this->is_subroutine)
355*61046927SAndroid Build Coastguard Worker continue;
356*61046927SAndroid Build Coastguard Worker inexact_matches_temp = (ir_function_signature **)
357*61046927SAndroid Build Coastguard Worker realloc(inexact_matches,
358*61046927SAndroid Build Coastguard Worker sizeof(*inexact_matches) *
359*61046927SAndroid Build Coastguard Worker (num_inexact_matches + 1));
360*61046927SAndroid Build Coastguard Worker if (inexact_matches_temp == NULL) {
361*61046927SAndroid Build Coastguard Worker _mesa_error_no_memory(__func__);
362*61046927SAndroid Build Coastguard Worker free(inexact_matches);
363*61046927SAndroid Build Coastguard Worker return NULL;
364*61046927SAndroid Build Coastguard Worker }
365*61046927SAndroid Build Coastguard Worker inexact_matches = inexact_matches_temp;
366*61046927SAndroid Build Coastguard Worker inexact_matches[num_inexact_matches++] = sig;
367*61046927SAndroid Build Coastguard Worker continue;
368*61046927SAndroid Build Coastguard Worker case PARAMETER_LIST_NO_MATCH:
369*61046927SAndroid Build Coastguard Worker continue;
370*61046927SAndroid Build Coastguard Worker default:
371*61046927SAndroid Build Coastguard Worker assert(false);
372*61046927SAndroid Build Coastguard Worker return NULL;
373*61046927SAndroid Build Coastguard Worker }
374*61046927SAndroid Build Coastguard Worker }
375*61046927SAndroid Build Coastguard Worker
376*61046927SAndroid Build Coastguard Worker /* There is no exact match (we would have returned it by now). If there
377*61046927SAndroid Build Coastguard Worker * are multiple inexact matches, the call is ambiguous, which is an error.
378*61046927SAndroid Build Coastguard Worker *
379*61046927SAndroid Build Coastguard Worker * FINISHME: Report a decent error. Returning NULL will likely result in
380*61046927SAndroid Build Coastguard Worker * FINISHME: a "no matching signature" error; it should report that the
381*61046927SAndroid Build Coastguard Worker * FINISHME: call is ambiguous. But reporting errors from here is hard.
382*61046927SAndroid Build Coastguard Worker */
383*61046927SAndroid Build Coastguard Worker *is_exact = false;
384*61046927SAndroid Build Coastguard Worker
385*61046927SAndroid Build Coastguard Worker match = choose_best_inexact_overload(state, actual_parameters,
386*61046927SAndroid Build Coastguard Worker inexact_matches, num_inexact_matches,
387*61046927SAndroid Build Coastguard Worker has_implicit_int_to_uint_conversion);
388*61046927SAndroid Build Coastguard Worker
389*61046927SAndroid Build Coastguard Worker free(inexact_matches);
390*61046927SAndroid Build Coastguard Worker return match;
391*61046927SAndroid Build Coastguard Worker }
392*61046927SAndroid Build Coastguard Worker
393*61046927SAndroid Build Coastguard Worker
394*61046927SAndroid Build Coastguard Worker static bool
parameter_lists_match_exact(const exec_list * list_a,const exec_list * list_b)395*61046927SAndroid Build Coastguard Worker parameter_lists_match_exact(const exec_list *list_a, const exec_list *list_b)
396*61046927SAndroid Build Coastguard Worker {
397*61046927SAndroid Build Coastguard Worker const exec_node *node_a = list_a->get_head_raw();
398*61046927SAndroid Build Coastguard Worker const exec_node *node_b = list_b->get_head_raw();
399*61046927SAndroid Build Coastguard Worker
400*61046927SAndroid Build Coastguard Worker for (/* empty */
401*61046927SAndroid Build Coastguard Worker ; !node_a->is_tail_sentinel() && !node_b->is_tail_sentinel()
402*61046927SAndroid Build Coastguard Worker ; node_a = node_a->next, node_b = node_b->next) {
403*61046927SAndroid Build Coastguard Worker ir_instruction *inst_a = (ir_instruction *) node_a;
404*61046927SAndroid Build Coastguard Worker ir_instruction *inst_b = (ir_instruction *) node_b;
405*61046927SAndroid Build Coastguard Worker
406*61046927SAndroid Build Coastguard Worker /* If the types of the parameters do not match, the parameters lists
407*61046927SAndroid Build Coastguard Worker * are different.
408*61046927SAndroid Build Coastguard Worker */
409*61046927SAndroid Build Coastguard Worker if (get_param_type (inst_a) != get_param_type (inst_b))
410*61046927SAndroid Build Coastguard Worker return false;
411*61046927SAndroid Build Coastguard Worker }
412*61046927SAndroid Build Coastguard Worker
413*61046927SAndroid Build Coastguard Worker /* Unless both lists are exhausted, they differ in length and, by
414*61046927SAndroid Build Coastguard Worker * definition, do not match.
415*61046927SAndroid Build Coastguard Worker */
416*61046927SAndroid Build Coastguard Worker return (node_a->is_tail_sentinel() == node_b->is_tail_sentinel());
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker
419*61046927SAndroid Build Coastguard Worker ir_function_signature *
exact_matching_signature(_mesa_glsl_parse_state * state,const exec_list * actual_parameters)420*61046927SAndroid Build Coastguard Worker ir_function::exact_matching_signature(_mesa_glsl_parse_state *state,
421*61046927SAndroid Build Coastguard Worker const exec_list *actual_parameters)
422*61046927SAndroid Build Coastguard Worker {
423*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_function_signature, sig, &this->signatures) {
424*61046927SAndroid Build Coastguard Worker /* Skip over any built-ins that aren't available in this shader. */
425*61046927SAndroid Build Coastguard Worker if (sig->is_builtin() && !sig->is_builtin_available(state))
426*61046927SAndroid Build Coastguard Worker continue;
427*61046927SAndroid Build Coastguard Worker
428*61046927SAndroid Build Coastguard Worker if (parameter_lists_match_exact(&sig->parameters, actual_parameters))
429*61046927SAndroid Build Coastguard Worker return sig;
430*61046927SAndroid Build Coastguard Worker }
431*61046927SAndroid Build Coastguard Worker return NULL;
432*61046927SAndroid Build Coastguard Worker }
433