Tizen 2.0 Release
[profile/ivi/osmesa.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 }