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