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 "glsl_symbol_table.h"
25*61046927SAndroid Build Coastguard Worker #include "ast.h"
26*61046927SAndroid Build Coastguard Worker #include "compiler/glsl_types.h"
27*61046927SAndroid Build Coastguard Worker #include "ir.h"
28*61046927SAndroid Build Coastguard Worker #include "linker_util.h"
29*61046927SAndroid Build Coastguard Worker #include "main/shader_types.h"
30*61046927SAndroid Build Coastguard Worker #include "main/consts_exts.h"
31*61046927SAndroid Build Coastguard Worker #include "main/shaderobj.h"
32*61046927SAndroid Build Coastguard Worker #include "builtin_functions.h"
33*61046927SAndroid Build Coastguard Worker
34*61046927SAndroid Build Coastguard Worker static ir_rvalue *
35*61046927SAndroid Build Coastguard Worker convert_component(ir_rvalue *src, const glsl_type *desired_type);
36*61046927SAndroid Build Coastguard Worker
37*61046927SAndroid Build Coastguard Worker static unsigned
process_parameters(exec_list * instructions,exec_list * actual_parameters,exec_list * parameters,struct _mesa_glsl_parse_state * state)38*61046927SAndroid Build Coastguard Worker process_parameters(exec_list *instructions, exec_list *actual_parameters,
39*61046927SAndroid Build Coastguard Worker exec_list *parameters,
40*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
41*61046927SAndroid Build Coastguard Worker {
42*61046927SAndroid Build Coastguard Worker void *mem_ctx = state;
43*61046927SAndroid Build Coastguard Worker unsigned count = 0;
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker foreach_list_typed(ast_node, ast, link, parameters) {
46*61046927SAndroid Build Coastguard Worker /* We need to process the parameters first in order to know if we can
47*61046927SAndroid Build Coastguard Worker * raise or not a unitialized warning. Calling set_is_lhs silence the
48*61046927SAndroid Build Coastguard Worker * warning for now. Raising the warning or not will be checked at
49*61046927SAndroid Build Coastguard Worker * verify_parameter_modes.
50*61046927SAndroid Build Coastguard Worker */
51*61046927SAndroid Build Coastguard Worker ast->set_is_lhs(true);
52*61046927SAndroid Build Coastguard Worker ir_rvalue *result = ast->hir(instructions, state);
53*61046927SAndroid Build Coastguard Worker
54*61046927SAndroid Build Coastguard Worker /* Error happened processing function parameter */
55*61046927SAndroid Build Coastguard Worker if (!result) {
56*61046927SAndroid Build Coastguard Worker actual_parameters->push_tail(ir_rvalue::error_value(mem_ctx));
57*61046927SAndroid Build Coastguard Worker count++;
58*61046927SAndroid Build Coastguard Worker continue;
59*61046927SAndroid Build Coastguard Worker }
60*61046927SAndroid Build Coastguard Worker
61*61046927SAndroid Build Coastguard Worker ir_constant *const constant =
62*61046927SAndroid Build Coastguard Worker result->constant_expression_value(mem_ctx);
63*61046927SAndroid Build Coastguard Worker
64*61046927SAndroid Build Coastguard Worker if (constant != NULL)
65*61046927SAndroid Build Coastguard Worker result = constant;
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker actual_parameters->push_tail(result);
68*61046927SAndroid Build Coastguard Worker count++;
69*61046927SAndroid Build Coastguard Worker }
70*61046927SAndroid Build Coastguard Worker
71*61046927SAndroid Build Coastguard Worker return count;
72*61046927SAndroid Build Coastguard Worker }
73*61046927SAndroid Build Coastguard Worker
74*61046927SAndroid Build Coastguard Worker
75*61046927SAndroid Build Coastguard Worker /**
76*61046927SAndroid Build Coastguard Worker * Generate a source prototype for a function signature
77*61046927SAndroid Build Coastguard Worker *
78*61046927SAndroid Build Coastguard Worker * \param return_type Return type of the function. May be \c NULL.
79*61046927SAndroid Build Coastguard Worker * \param name Name of the function.
80*61046927SAndroid Build Coastguard Worker * \param parameters List of \c ir_instruction nodes representing the
81*61046927SAndroid Build Coastguard Worker * parameter list for the function. This may be either a
82*61046927SAndroid Build Coastguard Worker * formal (\c ir_variable) or actual (\c ir_rvalue)
83*61046927SAndroid Build Coastguard Worker * parameter list. Only the type is used.
84*61046927SAndroid Build Coastguard Worker *
85*61046927SAndroid Build Coastguard Worker * \return
86*61046927SAndroid Build Coastguard Worker * A ralloced string representing the prototype of the function.
87*61046927SAndroid Build Coastguard Worker */
88*61046927SAndroid Build Coastguard Worker char *
prototype_string(const glsl_type * return_type,const char * name,exec_list * parameters)89*61046927SAndroid Build Coastguard Worker prototype_string(const glsl_type *return_type, const char *name,
90*61046927SAndroid Build Coastguard Worker exec_list *parameters)
91*61046927SAndroid Build Coastguard Worker {
92*61046927SAndroid Build Coastguard Worker char *str = NULL;
93*61046927SAndroid Build Coastguard Worker
94*61046927SAndroid Build Coastguard Worker if (return_type != NULL)
95*61046927SAndroid Build Coastguard Worker str = ralloc_asprintf(NULL, "%s ", glsl_get_type_name(return_type));
96*61046927SAndroid Build Coastguard Worker
97*61046927SAndroid Build Coastguard Worker ralloc_asprintf_append(&str, "%s(", name);
98*61046927SAndroid Build Coastguard Worker
99*61046927SAndroid Build Coastguard Worker const char *comma = "";
100*61046927SAndroid Build Coastguard Worker foreach_in_list(const ir_instruction, param, parameters) {
101*61046927SAndroid Build Coastguard Worker ralloc_asprintf_append(&str, "%s%s", comma,
102*61046927SAndroid Build Coastguard Worker glsl_get_type_name(param->ir_type ==
103*61046927SAndroid Build Coastguard Worker ir_type_variable ? ((ir_variable *)param)->type :
104*61046927SAndroid Build Coastguard Worker ((ir_rvalue *)param)->type));
105*61046927SAndroid Build Coastguard Worker comma = ", ";
106*61046927SAndroid Build Coastguard Worker }
107*61046927SAndroid Build Coastguard Worker
108*61046927SAndroid Build Coastguard Worker ralloc_strcat(&str, ")");
109*61046927SAndroid Build Coastguard Worker return str;
110*61046927SAndroid Build Coastguard Worker }
111*61046927SAndroid Build Coastguard Worker
112*61046927SAndroid Build Coastguard Worker static bool
verify_image_parameter(YYLTYPE * loc,_mesa_glsl_parse_state * state,const ir_variable * formal,const ir_variable * actual)113*61046927SAndroid Build Coastguard Worker verify_image_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state,
114*61046927SAndroid Build Coastguard Worker const ir_variable *formal, const ir_variable *actual)
115*61046927SAndroid Build Coastguard Worker {
116*61046927SAndroid Build Coastguard Worker /**
117*61046927SAndroid Build Coastguard Worker * From the ARB_shader_image_load_store specification:
118*61046927SAndroid Build Coastguard Worker *
119*61046927SAndroid Build Coastguard Worker * "The values of image variables qualified with coherent,
120*61046927SAndroid Build Coastguard Worker * volatile, restrict, readonly, or writeonly may not be passed
121*61046927SAndroid Build Coastguard Worker * to functions whose formal parameters lack such
122*61046927SAndroid Build Coastguard Worker * qualifiers. [...] It is legal to have additional qualifiers
123*61046927SAndroid Build Coastguard Worker * on a formal parameter, but not to have fewer."
124*61046927SAndroid Build Coastguard Worker */
125*61046927SAndroid Build Coastguard Worker if (actual->data.memory_coherent && !formal->data.memory_coherent) {
126*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
127*61046927SAndroid Build Coastguard Worker "function call parameter `%s' drops "
128*61046927SAndroid Build Coastguard Worker "`coherent' qualifier", formal->name);
129*61046927SAndroid Build Coastguard Worker return false;
130*61046927SAndroid Build Coastguard Worker }
131*61046927SAndroid Build Coastguard Worker
132*61046927SAndroid Build Coastguard Worker if (actual->data.memory_volatile && !formal->data.memory_volatile) {
133*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
134*61046927SAndroid Build Coastguard Worker "function call parameter `%s' drops "
135*61046927SAndroid Build Coastguard Worker "`volatile' qualifier", formal->name);
136*61046927SAndroid Build Coastguard Worker return false;
137*61046927SAndroid Build Coastguard Worker }
138*61046927SAndroid Build Coastguard Worker
139*61046927SAndroid Build Coastguard Worker if (actual->data.memory_restrict && !formal->data.memory_restrict) {
140*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
141*61046927SAndroid Build Coastguard Worker "function call parameter `%s' drops "
142*61046927SAndroid Build Coastguard Worker "`restrict' qualifier", formal->name);
143*61046927SAndroid Build Coastguard Worker return false;
144*61046927SAndroid Build Coastguard Worker }
145*61046927SAndroid Build Coastguard Worker
146*61046927SAndroid Build Coastguard Worker if (actual->data.memory_read_only && !formal->data.memory_read_only) {
147*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
148*61046927SAndroid Build Coastguard Worker "function call parameter `%s' drops "
149*61046927SAndroid Build Coastguard Worker "`readonly' qualifier", formal->name);
150*61046927SAndroid Build Coastguard Worker return false;
151*61046927SAndroid Build Coastguard Worker }
152*61046927SAndroid Build Coastguard Worker
153*61046927SAndroid Build Coastguard Worker if (actual->data.memory_write_only && !formal->data.memory_write_only) {
154*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
155*61046927SAndroid Build Coastguard Worker "function call parameter `%s' drops "
156*61046927SAndroid Build Coastguard Worker "`writeonly' qualifier", formal->name);
157*61046927SAndroid Build Coastguard Worker return false;
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker
160*61046927SAndroid Build Coastguard Worker return true;
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker static bool
verify_first_atomic_parameter(YYLTYPE * loc,_mesa_glsl_parse_state * state,ir_variable * var)164*61046927SAndroid Build Coastguard Worker verify_first_atomic_parameter(YYLTYPE *loc, _mesa_glsl_parse_state *state,
165*61046927SAndroid Build Coastguard Worker ir_variable *var)
166*61046927SAndroid Build Coastguard Worker {
167*61046927SAndroid Build Coastguard Worker if (!var ||
168*61046927SAndroid Build Coastguard Worker (!var->is_in_shader_storage_block() &&
169*61046927SAndroid Build Coastguard Worker var->data.mode != ir_var_shader_shared)) {
170*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "First argument to atomic function "
171*61046927SAndroid Build Coastguard Worker "must be a buffer or shared variable");
172*61046927SAndroid Build Coastguard Worker return false;
173*61046927SAndroid Build Coastguard Worker }
174*61046927SAndroid Build Coastguard Worker return true;
175*61046927SAndroid Build Coastguard Worker }
176*61046927SAndroid Build Coastguard Worker
177*61046927SAndroid Build Coastguard Worker static bool
is_atomic_function(const char * func_name)178*61046927SAndroid Build Coastguard Worker is_atomic_function(const char *func_name)
179*61046927SAndroid Build Coastguard Worker {
180*61046927SAndroid Build Coastguard Worker return !strcmp(func_name, "atomicAdd") ||
181*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "atomicMin") ||
182*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "atomicMax") ||
183*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "atomicAnd") ||
184*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "atomicOr") ||
185*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "atomicXor") ||
186*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "atomicExchange") ||
187*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "atomicCompSwap");
188*61046927SAndroid Build Coastguard Worker }
189*61046927SAndroid Build Coastguard Worker
190*61046927SAndroid Build Coastguard Worker static bool
verify_atomic_image_parameter_qualifier(YYLTYPE * loc,_mesa_glsl_parse_state * state,ir_variable * var)191*61046927SAndroid Build Coastguard Worker verify_atomic_image_parameter_qualifier(YYLTYPE *loc, _mesa_glsl_parse_state *state,
192*61046927SAndroid Build Coastguard Worker ir_variable *var)
193*61046927SAndroid Build Coastguard Worker {
194*61046927SAndroid Build Coastguard Worker if (!var ||
195*61046927SAndroid Build Coastguard Worker (var->data.image_format != PIPE_FORMAT_R32_UINT &&
196*61046927SAndroid Build Coastguard Worker var->data.image_format != PIPE_FORMAT_R32_SINT &&
197*61046927SAndroid Build Coastguard Worker var->data.image_format != PIPE_FORMAT_R32_FLOAT)) {
198*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "Image atomic functions should use r32i/r32ui "
199*61046927SAndroid Build Coastguard Worker "format qualifier");
200*61046927SAndroid Build Coastguard Worker return false;
201*61046927SAndroid Build Coastguard Worker }
202*61046927SAndroid Build Coastguard Worker return true;
203*61046927SAndroid Build Coastguard Worker }
204*61046927SAndroid Build Coastguard Worker
205*61046927SAndroid Build Coastguard Worker static bool
is_atomic_image_function(const char * func_name)206*61046927SAndroid Build Coastguard Worker is_atomic_image_function(const char *func_name)
207*61046927SAndroid Build Coastguard Worker {
208*61046927SAndroid Build Coastguard Worker return !strcmp(func_name, "imageAtomicAdd") ||
209*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicMin") ||
210*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicMax") ||
211*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicAnd") ||
212*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicOr") ||
213*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicXor") ||
214*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicExchange") ||
215*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicCompSwap") ||
216*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicIncWrap") ||
217*61046927SAndroid Build Coastguard Worker !strcmp(func_name, "imageAtomicDecWrap");
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker /**
222*61046927SAndroid Build Coastguard Worker * Verify that 'out' and 'inout' actual parameters are lvalues. Also, verify
223*61046927SAndroid Build Coastguard Worker * that 'const_in' formal parameters (an extension in our IR) correspond to
224*61046927SAndroid Build Coastguard Worker * ir_constant actual parameters.
225*61046927SAndroid Build Coastguard Worker */
226*61046927SAndroid Build Coastguard Worker static bool
verify_parameter_modes(_mesa_glsl_parse_state * state,ir_function_signature * sig,exec_list & actual_ir_parameters,exec_list & actual_ast_parameters)227*61046927SAndroid Build Coastguard Worker verify_parameter_modes(_mesa_glsl_parse_state *state,
228*61046927SAndroid Build Coastguard Worker ir_function_signature *sig,
229*61046927SAndroid Build Coastguard Worker exec_list &actual_ir_parameters,
230*61046927SAndroid Build Coastguard Worker exec_list &actual_ast_parameters)
231*61046927SAndroid Build Coastguard Worker {
232*61046927SAndroid Build Coastguard Worker exec_node *actual_ir_node = actual_ir_parameters.get_head_raw();
233*61046927SAndroid Build Coastguard Worker exec_node *actual_ast_node = actual_ast_parameters.get_head_raw();
234*61046927SAndroid Build Coastguard Worker
235*61046927SAndroid Build Coastguard Worker foreach_in_list(const ir_variable, formal, &sig->parameters) {
236*61046927SAndroid Build Coastguard Worker /* The lists must be the same length. */
237*61046927SAndroid Build Coastguard Worker assert(!actual_ir_node->is_tail_sentinel());
238*61046927SAndroid Build Coastguard Worker assert(!actual_ast_node->is_tail_sentinel());
239*61046927SAndroid Build Coastguard Worker
240*61046927SAndroid Build Coastguard Worker const ir_rvalue *const actual = (ir_rvalue *) actual_ir_node;
241*61046927SAndroid Build Coastguard Worker const ast_expression *const actual_ast =
242*61046927SAndroid Build Coastguard Worker exec_node_data(ast_expression, actual_ast_node, link);
243*61046927SAndroid Build Coastguard Worker
244*61046927SAndroid Build Coastguard Worker YYLTYPE loc = actual_ast->get_location();
245*61046927SAndroid Build Coastguard Worker
246*61046927SAndroid Build Coastguard Worker /* Verify that 'const_in' parameters are ir_constants. */
247*61046927SAndroid Build Coastguard Worker if (formal->data.mode == ir_var_const_in &&
248*61046927SAndroid Build Coastguard Worker actual->ir_type != ir_type_constant) {
249*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
250*61046927SAndroid Build Coastguard Worker "parameter `in %s' must be a constant expression",
251*61046927SAndroid Build Coastguard Worker formal->name);
252*61046927SAndroid Build Coastguard Worker return false;
253*61046927SAndroid Build Coastguard Worker }
254*61046927SAndroid Build Coastguard Worker
255*61046927SAndroid Build Coastguard Worker /* Verify that shader_in parameters are shader inputs */
256*61046927SAndroid Build Coastguard Worker if (formal->data.must_be_shader_input) {
257*61046927SAndroid Build Coastguard Worker const ir_rvalue *val = actual;
258*61046927SAndroid Build Coastguard Worker
259*61046927SAndroid Build Coastguard Worker /* GLSL 4.40 allows swizzles, while earlier GLSL versions do not. */
260*61046927SAndroid Build Coastguard Worker if (val->ir_type == ir_type_swizzle) {
261*61046927SAndroid Build Coastguard Worker if (!state->is_version(440, 0)) {
262*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
263*61046927SAndroid Build Coastguard Worker "parameter `%s` must not be swizzled",
264*61046927SAndroid Build Coastguard Worker formal->name);
265*61046927SAndroid Build Coastguard Worker return false;
266*61046927SAndroid Build Coastguard Worker }
267*61046927SAndroid Build Coastguard Worker val = ((ir_swizzle *)val)->val;
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker for (;;) {
271*61046927SAndroid Build Coastguard Worker if (val->ir_type == ir_type_dereference_array) {
272*61046927SAndroid Build Coastguard Worker val = ((ir_dereference_array *)val)->array;
273*61046927SAndroid Build Coastguard Worker } else if (val->ir_type == ir_type_dereference_record &&
274*61046927SAndroid Build Coastguard Worker !state->es_shader) {
275*61046927SAndroid Build Coastguard Worker val = ((ir_dereference_record *)val)->record;
276*61046927SAndroid Build Coastguard Worker } else
277*61046927SAndroid Build Coastguard Worker break;
278*61046927SAndroid Build Coastguard Worker }
279*61046927SAndroid Build Coastguard Worker
280*61046927SAndroid Build Coastguard Worker ir_variable *var = NULL;
281*61046927SAndroid Build Coastguard Worker if (const ir_dereference_variable *deref_var = val->as_dereference_variable())
282*61046927SAndroid Build Coastguard Worker var = deref_var->variable_referenced();
283*61046927SAndroid Build Coastguard Worker
284*61046927SAndroid Build Coastguard Worker if (!var || var->data.mode != ir_var_shader_in) {
285*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
286*61046927SAndroid Build Coastguard Worker "parameter `%s` must be a shader input",
287*61046927SAndroid Build Coastguard Worker formal->name);
288*61046927SAndroid Build Coastguard Worker return false;
289*61046927SAndroid Build Coastguard Worker }
290*61046927SAndroid Build Coastguard Worker
291*61046927SAndroid Build Coastguard Worker var->data.must_be_shader_input = 1;
292*61046927SAndroid Build Coastguard Worker }
293*61046927SAndroid Build Coastguard Worker
294*61046927SAndroid Build Coastguard Worker /* Verify that 'out' and 'inout' actual parameters are lvalues. */
295*61046927SAndroid Build Coastguard Worker if (formal->data.mode == ir_var_function_out
296*61046927SAndroid Build Coastguard Worker || formal->data.mode == ir_var_function_inout) {
297*61046927SAndroid Build Coastguard Worker const char *mode = NULL;
298*61046927SAndroid Build Coastguard Worker switch (formal->data.mode) {
299*61046927SAndroid Build Coastguard Worker case ir_var_function_out: mode = "out"; break;
300*61046927SAndroid Build Coastguard Worker case ir_var_function_inout: mode = "inout"; break;
301*61046927SAndroid Build Coastguard Worker default: assert(false); break;
302*61046927SAndroid Build Coastguard Worker }
303*61046927SAndroid Build Coastguard Worker
304*61046927SAndroid Build Coastguard Worker /* This AST-based check catches errors like f(i++). The IR-based
305*61046927SAndroid Build Coastguard Worker * is_lvalue() is insufficient because the actual parameter at the
306*61046927SAndroid Build Coastguard Worker * IR-level is just a temporary value, which is an l-value.
307*61046927SAndroid Build Coastguard Worker */
308*61046927SAndroid Build Coastguard Worker if (actual_ast->non_lvalue_description != NULL) {
309*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
310*61046927SAndroid Build Coastguard Worker "function parameter '%s %s' references a %s",
311*61046927SAndroid Build Coastguard Worker mode, formal->name,
312*61046927SAndroid Build Coastguard Worker actual_ast->non_lvalue_description);
313*61046927SAndroid Build Coastguard Worker return false;
314*61046927SAndroid Build Coastguard Worker }
315*61046927SAndroid Build Coastguard Worker
316*61046927SAndroid Build Coastguard Worker ir_variable *var = actual->variable_referenced();
317*61046927SAndroid Build Coastguard Worker
318*61046927SAndroid Build Coastguard Worker if (var && formal->data.mode == ir_var_function_inout) {
319*61046927SAndroid Build Coastguard Worker if ((var->data.mode == ir_var_auto ||
320*61046927SAndroid Build Coastguard Worker var->data.mode == ir_var_shader_out) &&
321*61046927SAndroid Build Coastguard Worker !var->data.assigned &&
322*61046927SAndroid Build Coastguard Worker !is_gl_identifier(var->name)) {
323*61046927SAndroid Build Coastguard Worker _mesa_glsl_warning(&loc, state, "`%s' used uninitialized",
324*61046927SAndroid Build Coastguard Worker var->name);
325*61046927SAndroid Build Coastguard Worker }
326*61046927SAndroid Build Coastguard Worker }
327*61046927SAndroid Build Coastguard Worker
328*61046927SAndroid Build Coastguard Worker if (var)
329*61046927SAndroid Build Coastguard Worker var->data.assigned = true;
330*61046927SAndroid Build Coastguard Worker
331*61046927SAndroid Build Coastguard Worker if (var && var->data.read_only) {
332*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
333*61046927SAndroid Build Coastguard Worker "function parameter '%s %s' references the "
334*61046927SAndroid Build Coastguard Worker "read-only variable '%s'",
335*61046927SAndroid Build Coastguard Worker mode, formal->name,
336*61046927SAndroid Build Coastguard Worker actual->variable_referenced()->name);
337*61046927SAndroid Build Coastguard Worker return false;
338*61046927SAndroid Build Coastguard Worker } else if (!actual->is_lvalue(state)) {
339*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
340*61046927SAndroid Build Coastguard Worker "function parameter '%s %s' is not an lvalue",
341*61046927SAndroid Build Coastguard Worker mode, formal->name);
342*61046927SAndroid Build Coastguard Worker return false;
343*61046927SAndroid Build Coastguard Worker }
344*61046927SAndroid Build Coastguard Worker } else {
345*61046927SAndroid Build Coastguard Worker assert(formal->data.mode == ir_var_function_in ||
346*61046927SAndroid Build Coastguard Worker formal->data.mode == ir_var_const_in);
347*61046927SAndroid Build Coastguard Worker ir_variable *var = actual->variable_referenced();
348*61046927SAndroid Build Coastguard Worker if (var) {
349*61046927SAndroid Build Coastguard Worker if ((var->data.mode == ir_var_auto ||
350*61046927SAndroid Build Coastguard Worker var->data.mode == ir_var_shader_out) &&
351*61046927SAndroid Build Coastguard Worker !var->data.assigned &&
352*61046927SAndroid Build Coastguard Worker !is_gl_identifier(var->name)) {
353*61046927SAndroid Build Coastguard Worker _mesa_glsl_warning(&loc, state, "`%s' used uninitialized",
354*61046927SAndroid Build Coastguard Worker var->name);
355*61046927SAndroid Build Coastguard Worker }
356*61046927SAndroid Build Coastguard Worker }
357*61046927SAndroid Build Coastguard Worker }
358*61046927SAndroid Build Coastguard Worker
359*61046927SAndroid Build Coastguard Worker if (glsl_type_is_image(formal->type) &&
360*61046927SAndroid Build Coastguard Worker actual->variable_referenced()) {
361*61046927SAndroid Build Coastguard Worker if (!verify_image_parameter(&loc, state, formal,
362*61046927SAndroid Build Coastguard Worker actual->variable_referenced()))
363*61046927SAndroid Build Coastguard Worker return false;
364*61046927SAndroid Build Coastguard Worker }
365*61046927SAndroid Build Coastguard Worker
366*61046927SAndroid Build Coastguard Worker actual_ir_node = actual_ir_node->next;
367*61046927SAndroid Build Coastguard Worker actual_ast_node = actual_ast_node->next;
368*61046927SAndroid Build Coastguard Worker }
369*61046927SAndroid Build Coastguard Worker
370*61046927SAndroid Build Coastguard Worker /* The first parameter of atomic functions must be a buffer variable */
371*61046927SAndroid Build Coastguard Worker const char *func_name = sig->function_name();
372*61046927SAndroid Build Coastguard Worker bool is_atomic = is_atomic_function(func_name);
373*61046927SAndroid Build Coastguard Worker if (is_atomic) {
374*61046927SAndroid Build Coastguard Worker const ir_rvalue *const actual =
375*61046927SAndroid Build Coastguard Worker (ir_rvalue *) actual_ir_parameters.get_head_raw();
376*61046927SAndroid Build Coastguard Worker
377*61046927SAndroid Build Coastguard Worker const ast_expression *const actual_ast =
378*61046927SAndroid Build Coastguard Worker exec_node_data(ast_expression,
379*61046927SAndroid Build Coastguard Worker actual_ast_parameters.get_head_raw(), link);
380*61046927SAndroid Build Coastguard Worker YYLTYPE loc = actual_ast->get_location();
381*61046927SAndroid Build Coastguard Worker
382*61046927SAndroid Build Coastguard Worker if (!verify_first_atomic_parameter(&loc, state,
383*61046927SAndroid Build Coastguard Worker actual->variable_referenced())) {
384*61046927SAndroid Build Coastguard Worker return false;
385*61046927SAndroid Build Coastguard Worker }
386*61046927SAndroid Build Coastguard Worker } else if (is_atomic_image_function(func_name)) {
387*61046927SAndroid Build Coastguard Worker const ir_rvalue *const actual =
388*61046927SAndroid Build Coastguard Worker (ir_rvalue *) actual_ir_parameters.get_head_raw();
389*61046927SAndroid Build Coastguard Worker
390*61046927SAndroid Build Coastguard Worker const ast_expression *const actual_ast =
391*61046927SAndroid Build Coastguard Worker exec_node_data(ast_expression,
392*61046927SAndroid Build Coastguard Worker actual_ast_parameters.get_head_raw(), link);
393*61046927SAndroid Build Coastguard Worker YYLTYPE loc = actual_ast->get_location();
394*61046927SAndroid Build Coastguard Worker
395*61046927SAndroid Build Coastguard Worker if (!verify_atomic_image_parameter_qualifier(&loc, state,
396*61046927SAndroid Build Coastguard Worker actual->variable_referenced())) {
397*61046927SAndroid Build Coastguard Worker return false;
398*61046927SAndroid Build Coastguard Worker }
399*61046927SAndroid Build Coastguard Worker }
400*61046927SAndroid Build Coastguard Worker
401*61046927SAndroid Build Coastguard Worker return true;
402*61046927SAndroid Build Coastguard Worker }
403*61046927SAndroid Build Coastguard Worker
404*61046927SAndroid Build Coastguard Worker struct copy_index_deref_data {
405*61046927SAndroid Build Coastguard Worker void *mem_ctx;
406*61046927SAndroid Build Coastguard Worker exec_list *before_instructions;
407*61046927SAndroid Build Coastguard Worker };
408*61046927SAndroid Build Coastguard Worker
409*61046927SAndroid Build Coastguard Worker static void
copy_index_derefs_to_temps(ir_instruction * ir,void * data)410*61046927SAndroid Build Coastguard Worker copy_index_derefs_to_temps(ir_instruction *ir, void *data)
411*61046927SAndroid Build Coastguard Worker {
412*61046927SAndroid Build Coastguard Worker struct copy_index_deref_data *d = (struct copy_index_deref_data *)data;
413*61046927SAndroid Build Coastguard Worker
414*61046927SAndroid Build Coastguard Worker if (ir->ir_type == ir_type_dereference_array) {
415*61046927SAndroid Build Coastguard Worker ir_dereference_array *a = (ir_dereference_array *) ir;
416*61046927SAndroid Build Coastguard Worker ir = a->array->as_dereference();
417*61046927SAndroid Build Coastguard Worker
418*61046927SAndroid Build Coastguard Worker ir_rvalue *idx = a->array_index;
419*61046927SAndroid Build Coastguard Worker ir_variable *var = idx->variable_referenced();
420*61046927SAndroid Build Coastguard Worker
421*61046927SAndroid Build Coastguard Worker /* If the index is read only it cannot change so there is no need
422*61046927SAndroid Build Coastguard Worker * to copy it.
423*61046927SAndroid Build Coastguard Worker */
424*61046927SAndroid Build Coastguard Worker if (!var || var->data.read_only || var->data.memory_read_only)
425*61046927SAndroid Build Coastguard Worker return;
426*61046927SAndroid Build Coastguard Worker
427*61046927SAndroid Build Coastguard Worker ir_variable *tmp = new(d->mem_ctx) ir_variable(idx->type, "idx_tmp",
428*61046927SAndroid Build Coastguard Worker ir_var_temporary);
429*61046927SAndroid Build Coastguard Worker d->before_instructions->push_tail(tmp);
430*61046927SAndroid Build Coastguard Worker
431*61046927SAndroid Build Coastguard Worker ir_dereference_variable *const deref_tmp_1 =
432*61046927SAndroid Build Coastguard Worker new(d->mem_ctx) ir_dereference_variable(tmp);
433*61046927SAndroid Build Coastguard Worker ir_assignment *const assignment =
434*61046927SAndroid Build Coastguard Worker new(d->mem_ctx) ir_assignment(deref_tmp_1,
435*61046927SAndroid Build Coastguard Worker idx->clone(d->mem_ctx, NULL));
436*61046927SAndroid Build Coastguard Worker d->before_instructions->push_tail(assignment);
437*61046927SAndroid Build Coastguard Worker
438*61046927SAndroid Build Coastguard Worker /* Replace the array index with a dereference of the new temporary */
439*61046927SAndroid Build Coastguard Worker ir_dereference_variable *const deref_tmp_2 =
440*61046927SAndroid Build Coastguard Worker new(d->mem_ctx) ir_dereference_variable(tmp);
441*61046927SAndroid Build Coastguard Worker a->array_index = deref_tmp_2;
442*61046927SAndroid Build Coastguard Worker }
443*61046927SAndroid Build Coastguard Worker }
444*61046927SAndroid Build Coastguard Worker
445*61046927SAndroid Build Coastguard Worker static void
fix_parameter(void * mem_ctx,ir_rvalue * actual,const glsl_type * formal_type,exec_list * before_instructions,exec_list * after_instructions,bool parameter_is_inout)446*61046927SAndroid Build Coastguard Worker fix_parameter(void *mem_ctx, ir_rvalue *actual, const glsl_type *formal_type,
447*61046927SAndroid Build Coastguard Worker exec_list *before_instructions, exec_list *after_instructions,
448*61046927SAndroid Build Coastguard Worker bool parameter_is_inout)
449*61046927SAndroid Build Coastguard Worker {
450*61046927SAndroid Build Coastguard Worker ir_expression *const expr = actual->as_expression();
451*61046927SAndroid Build Coastguard Worker
452*61046927SAndroid Build Coastguard Worker /* If the types match exactly and the parameter is not a vector-extract,
453*61046927SAndroid Build Coastguard Worker * nothing needs to be done to fix the parameter.
454*61046927SAndroid Build Coastguard Worker */
455*61046927SAndroid Build Coastguard Worker if (formal_type == actual->type
456*61046927SAndroid Build Coastguard Worker && (expr == NULL || expr->operation != ir_binop_vector_extract)
457*61046927SAndroid Build Coastguard Worker && actual->as_dereference_variable())
458*61046927SAndroid Build Coastguard Worker return;
459*61046927SAndroid Build Coastguard Worker
460*61046927SAndroid Build Coastguard Worker /* An array index could also be an out variable so we need to make a copy
461*61046927SAndroid Build Coastguard Worker * of them before the function is called.
462*61046927SAndroid Build Coastguard Worker */
463*61046927SAndroid Build Coastguard Worker if (!actual->as_dereference_variable()) {
464*61046927SAndroid Build Coastguard Worker struct copy_index_deref_data data;
465*61046927SAndroid Build Coastguard Worker data.mem_ctx = mem_ctx;
466*61046927SAndroid Build Coastguard Worker data.before_instructions = before_instructions;
467*61046927SAndroid Build Coastguard Worker
468*61046927SAndroid Build Coastguard Worker visit_tree(actual, copy_index_derefs_to_temps, &data);
469*61046927SAndroid Build Coastguard Worker }
470*61046927SAndroid Build Coastguard Worker
471*61046927SAndroid Build Coastguard Worker /* To convert an out parameter, we need to create a temporary variable to
472*61046927SAndroid Build Coastguard Worker * hold the value before conversion, and then perform the conversion after
473*61046927SAndroid Build Coastguard Worker * the function call returns.
474*61046927SAndroid Build Coastguard Worker *
475*61046927SAndroid Build Coastguard Worker * This has the effect of transforming code like this:
476*61046927SAndroid Build Coastguard Worker *
477*61046927SAndroid Build Coastguard Worker * void f(out int x);
478*61046927SAndroid Build Coastguard Worker * float value;
479*61046927SAndroid Build Coastguard Worker * f(value);
480*61046927SAndroid Build Coastguard Worker *
481*61046927SAndroid Build Coastguard Worker * Into IR that's equivalent to this:
482*61046927SAndroid Build Coastguard Worker *
483*61046927SAndroid Build Coastguard Worker * void f(out int x);
484*61046927SAndroid Build Coastguard Worker * float value;
485*61046927SAndroid Build Coastguard Worker * int out_parameter_conversion;
486*61046927SAndroid Build Coastguard Worker * f(out_parameter_conversion);
487*61046927SAndroid Build Coastguard Worker * value = float(out_parameter_conversion);
488*61046927SAndroid Build Coastguard Worker *
489*61046927SAndroid Build Coastguard Worker * If the parameter is an ir_expression of ir_binop_vector_extract,
490*61046927SAndroid Build Coastguard Worker * additional conversion is needed in the post-call re-write.
491*61046927SAndroid Build Coastguard Worker */
492*61046927SAndroid Build Coastguard Worker ir_variable *tmp =
493*61046927SAndroid Build Coastguard Worker new(mem_ctx) ir_variable(formal_type, "inout_tmp", ir_var_temporary);
494*61046927SAndroid Build Coastguard Worker
495*61046927SAndroid Build Coastguard Worker before_instructions->push_tail(tmp);
496*61046927SAndroid Build Coastguard Worker
497*61046927SAndroid Build Coastguard Worker /* If the parameter is an inout parameter, copy the value of the actual
498*61046927SAndroid Build Coastguard Worker * parameter to the new temporary. Note that no type conversion is allowed
499*61046927SAndroid Build Coastguard Worker * here because inout parameters must match types exactly.
500*61046927SAndroid Build Coastguard Worker */
501*61046927SAndroid Build Coastguard Worker if (parameter_is_inout) {
502*61046927SAndroid Build Coastguard Worker /* Inout parameters should never require conversion, since that would
503*61046927SAndroid Build Coastguard Worker * require an implicit conversion to exist both to and from the formal
504*61046927SAndroid Build Coastguard Worker * parameter type, and there are no bidirectional implicit conversions.
505*61046927SAndroid Build Coastguard Worker */
506*61046927SAndroid Build Coastguard Worker assert (actual->type == formal_type);
507*61046927SAndroid Build Coastguard Worker
508*61046927SAndroid Build Coastguard Worker ir_dereference_variable *const deref_tmp_1 =
509*61046927SAndroid Build Coastguard Worker new(mem_ctx) ir_dereference_variable(tmp);
510*61046927SAndroid Build Coastguard Worker ir_assignment *const assignment =
511*61046927SAndroid Build Coastguard Worker new(mem_ctx) ir_assignment(deref_tmp_1, actual->clone(mem_ctx, NULL));
512*61046927SAndroid Build Coastguard Worker before_instructions->push_tail(assignment);
513*61046927SAndroid Build Coastguard Worker }
514*61046927SAndroid Build Coastguard Worker
515*61046927SAndroid Build Coastguard Worker /* Replace the parameter in the call with a dereference of the new
516*61046927SAndroid Build Coastguard Worker * temporary.
517*61046927SAndroid Build Coastguard Worker */
518*61046927SAndroid Build Coastguard Worker ir_dereference_variable *const deref_tmp_2 =
519*61046927SAndroid Build Coastguard Worker new(mem_ctx) ir_dereference_variable(tmp);
520*61046927SAndroid Build Coastguard Worker actual->replace_with(deref_tmp_2);
521*61046927SAndroid Build Coastguard Worker
522*61046927SAndroid Build Coastguard Worker
523*61046927SAndroid Build Coastguard Worker /* Copy the temporary variable to the actual parameter with optional
524*61046927SAndroid Build Coastguard Worker * type conversion applied.
525*61046927SAndroid Build Coastguard Worker */
526*61046927SAndroid Build Coastguard Worker ir_rvalue *rhs = new(mem_ctx) ir_dereference_variable(tmp);
527*61046927SAndroid Build Coastguard Worker if (actual->type != formal_type)
528*61046927SAndroid Build Coastguard Worker rhs = convert_component(rhs, actual->type);
529*61046927SAndroid Build Coastguard Worker
530*61046927SAndroid Build Coastguard Worker ir_rvalue *lhs = actual;
531*61046927SAndroid Build Coastguard Worker if (expr != NULL && expr->operation == ir_binop_vector_extract) {
532*61046927SAndroid Build Coastguard Worker lhs = new(mem_ctx) ir_dereference_array(expr->operands[0]->clone(mem_ctx,
533*61046927SAndroid Build Coastguard Worker NULL),
534*61046927SAndroid Build Coastguard Worker expr->operands[1]->clone(mem_ctx,
535*61046927SAndroid Build Coastguard Worker NULL));
536*61046927SAndroid Build Coastguard Worker }
537*61046927SAndroid Build Coastguard Worker
538*61046927SAndroid Build Coastguard Worker ir_assignment *const assignment_2 = new(mem_ctx) ir_assignment(lhs, rhs);
539*61046927SAndroid Build Coastguard Worker after_instructions->push_tail(assignment_2);
540*61046927SAndroid Build Coastguard Worker }
541*61046927SAndroid Build Coastguard Worker
542*61046927SAndroid Build Coastguard Worker /**
543*61046927SAndroid Build Coastguard Worker * Generate a function call.
544*61046927SAndroid Build Coastguard Worker *
545*61046927SAndroid Build Coastguard Worker * For non-void functions, this returns a dereference of the temporary
546*61046927SAndroid Build Coastguard Worker * variable which stores the return value for the call. For void functions,
547*61046927SAndroid Build Coastguard Worker * this returns NULL.
548*61046927SAndroid Build Coastguard Worker */
549*61046927SAndroid Build Coastguard Worker static ir_rvalue *
generate_call(exec_list * instructions,ir_function_signature * sig,exec_list * actual_parameters,ir_variable * sub_var,ir_rvalue * array_idx,struct _mesa_glsl_parse_state * state)550*61046927SAndroid Build Coastguard Worker generate_call(exec_list *instructions, ir_function_signature *sig,
551*61046927SAndroid Build Coastguard Worker exec_list *actual_parameters,
552*61046927SAndroid Build Coastguard Worker ir_variable *sub_var,
553*61046927SAndroid Build Coastguard Worker ir_rvalue *array_idx,
554*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
555*61046927SAndroid Build Coastguard Worker {
556*61046927SAndroid Build Coastguard Worker void *ctx = state;
557*61046927SAndroid Build Coastguard Worker exec_list post_call_conversions;
558*61046927SAndroid Build Coastguard Worker
559*61046927SAndroid Build Coastguard Worker /* Perform implicit conversion of arguments. For out parameters, we need
560*61046927SAndroid Build Coastguard Worker * to place them in a temporary variable and do the conversion after the
561*61046927SAndroid Build Coastguard Worker * call takes place. Since we haven't emitted the call yet, we'll place
562*61046927SAndroid Build Coastguard Worker * the post-call conversions in a temporary exec_list, and emit them later.
563*61046927SAndroid Build Coastguard Worker */
564*61046927SAndroid Build Coastguard Worker foreach_two_lists(formal_node, &sig->parameters,
565*61046927SAndroid Build Coastguard Worker actual_node, actual_parameters) {
566*61046927SAndroid Build Coastguard Worker ir_rvalue *actual = (ir_rvalue *) actual_node;
567*61046927SAndroid Build Coastguard Worker ir_variable *formal = (ir_variable *) formal_node;
568*61046927SAndroid Build Coastguard Worker
569*61046927SAndroid Build Coastguard Worker if (glsl_type_is_numeric(formal->type) || glsl_type_is_boolean(formal->type)) {
570*61046927SAndroid Build Coastguard Worker switch (formal->data.mode) {
571*61046927SAndroid Build Coastguard Worker case ir_var_const_in:
572*61046927SAndroid Build Coastguard Worker case ir_var_function_in: {
573*61046927SAndroid Build Coastguard Worker ir_rvalue *converted
574*61046927SAndroid Build Coastguard Worker = convert_component(actual, formal->type);
575*61046927SAndroid Build Coastguard Worker actual->replace_with(converted);
576*61046927SAndroid Build Coastguard Worker break;
577*61046927SAndroid Build Coastguard Worker }
578*61046927SAndroid Build Coastguard Worker case ir_var_function_out:
579*61046927SAndroid Build Coastguard Worker case ir_var_function_inout:
580*61046927SAndroid Build Coastguard Worker fix_parameter(ctx, actual, formal->type,
581*61046927SAndroid Build Coastguard Worker instructions, &post_call_conversions,
582*61046927SAndroid Build Coastguard Worker formal->data.mode == ir_var_function_inout);
583*61046927SAndroid Build Coastguard Worker break;
584*61046927SAndroid Build Coastguard Worker default:
585*61046927SAndroid Build Coastguard Worker assert (!"Illegal formal parameter mode");
586*61046927SAndroid Build Coastguard Worker break;
587*61046927SAndroid Build Coastguard Worker }
588*61046927SAndroid Build Coastguard Worker }
589*61046927SAndroid Build Coastguard Worker }
590*61046927SAndroid Build Coastguard Worker
591*61046927SAndroid Build Coastguard Worker /* Section 4.3.2 (Const) of the GLSL 1.10.59 spec says:
592*61046927SAndroid Build Coastguard Worker *
593*61046927SAndroid Build Coastguard Worker * "Initializers for const declarations must be formed from literal
594*61046927SAndroid Build Coastguard Worker * values, other const variables (not including function call
595*61046927SAndroid Build Coastguard Worker * paramaters), or expressions of these.
596*61046927SAndroid Build Coastguard Worker *
597*61046927SAndroid Build Coastguard Worker * Constructors may be used in such expressions, but function calls may
598*61046927SAndroid Build Coastguard Worker * not."
599*61046927SAndroid Build Coastguard Worker *
600*61046927SAndroid Build Coastguard Worker * Section 4.3.3 (Constant Expressions) of the GLSL 1.20.8 spec says:
601*61046927SAndroid Build Coastguard Worker *
602*61046927SAndroid Build Coastguard Worker * "A constant expression is one of
603*61046927SAndroid Build Coastguard Worker *
604*61046927SAndroid Build Coastguard Worker * ...
605*61046927SAndroid Build Coastguard Worker *
606*61046927SAndroid Build Coastguard Worker * - a built-in function call whose arguments are all constant
607*61046927SAndroid Build Coastguard Worker * expressions, with the exception of the texture lookup
608*61046927SAndroid Build Coastguard Worker * functions, the noise functions, and ftransform. The built-in
609*61046927SAndroid Build Coastguard Worker * functions dFdx, dFdy, and fwidth must return 0 when evaluated
610*61046927SAndroid Build Coastguard Worker * inside an initializer with an argument that is a constant
611*61046927SAndroid Build Coastguard Worker * expression."
612*61046927SAndroid Build Coastguard Worker *
613*61046927SAndroid Build Coastguard Worker * Section 5.10 (Constant Expressions) of the GLSL ES 1.00.17 spec says:
614*61046927SAndroid Build Coastguard Worker *
615*61046927SAndroid Build Coastguard Worker * "A constant expression is one of
616*61046927SAndroid Build Coastguard Worker *
617*61046927SAndroid Build Coastguard Worker * ...
618*61046927SAndroid Build Coastguard Worker *
619*61046927SAndroid Build Coastguard Worker * - a built-in function call whose arguments are all constant
620*61046927SAndroid Build Coastguard Worker * expressions, with the exception of the texture lookup
621*61046927SAndroid Build Coastguard Worker * functions."
622*61046927SAndroid Build Coastguard Worker *
623*61046927SAndroid Build Coastguard Worker * Section 4.3.3 (Constant Expressions) of the GLSL ES 3.00.4 spec says:
624*61046927SAndroid Build Coastguard Worker *
625*61046927SAndroid Build Coastguard Worker * "A constant expression is one of
626*61046927SAndroid Build Coastguard Worker *
627*61046927SAndroid Build Coastguard Worker * ...
628*61046927SAndroid Build Coastguard Worker *
629*61046927SAndroid Build Coastguard Worker * - a built-in function call whose arguments are all constant
630*61046927SAndroid Build Coastguard Worker * expressions, with the exception of the texture lookup
631*61046927SAndroid Build Coastguard Worker * functions. The built-in functions dFdx, dFdy, and fwidth must
632*61046927SAndroid Build Coastguard Worker * return 0 when evaluated inside an initializer with an argument
633*61046927SAndroid Build Coastguard Worker * that is a constant expression."
634*61046927SAndroid Build Coastguard Worker *
635*61046927SAndroid Build Coastguard Worker * If the function call is a constant expression, don't generate any
636*61046927SAndroid Build Coastguard Worker * instructions; just generate an ir_constant.
637*61046927SAndroid Build Coastguard Worker */
638*61046927SAndroid Build Coastguard Worker if (state->is_version(120, 100) ||
639*61046927SAndroid Build Coastguard Worker state->consts->AllowGLSLBuiltinConstantExpression) {
640*61046927SAndroid Build Coastguard Worker ir_constant *value = sig->constant_expression_value(ctx,
641*61046927SAndroid Build Coastguard Worker actual_parameters,
642*61046927SAndroid Build Coastguard Worker NULL);
643*61046927SAndroid Build Coastguard Worker if (value != NULL) {
644*61046927SAndroid Build Coastguard Worker return value;
645*61046927SAndroid Build Coastguard Worker }
646*61046927SAndroid Build Coastguard Worker }
647*61046927SAndroid Build Coastguard Worker
648*61046927SAndroid Build Coastguard Worker ir_dereference_variable *deref = NULL;
649*61046927SAndroid Build Coastguard Worker if (!glsl_type_is_void(sig->return_type)) {
650*61046927SAndroid Build Coastguard Worker /* Create a new temporary to hold the return value. */
651*61046927SAndroid Build Coastguard Worker char *const name = ir_variable::temporaries_allocate_names
652*61046927SAndroid Build Coastguard Worker ? ralloc_asprintf(ctx, "%s_retval", sig->function_name())
653*61046927SAndroid Build Coastguard Worker : NULL;
654*61046927SAndroid Build Coastguard Worker
655*61046927SAndroid Build Coastguard Worker ir_variable *var;
656*61046927SAndroid Build Coastguard Worker
657*61046927SAndroid Build Coastguard Worker var = new(ctx) ir_variable(sig->return_type, name, ir_var_temporary);
658*61046927SAndroid Build Coastguard Worker var->data.precision = sig->return_precision;
659*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
660*61046927SAndroid Build Coastguard Worker
661*61046927SAndroid Build Coastguard Worker ralloc_free(name);
662*61046927SAndroid Build Coastguard Worker
663*61046927SAndroid Build Coastguard Worker deref = new(ctx) ir_dereference_variable(var);
664*61046927SAndroid Build Coastguard Worker }
665*61046927SAndroid Build Coastguard Worker
666*61046927SAndroid Build Coastguard Worker ir_call *call = new(ctx) ir_call(sig, deref,
667*61046927SAndroid Build Coastguard Worker actual_parameters, sub_var, array_idx);
668*61046927SAndroid Build Coastguard Worker instructions->push_tail(call);
669*61046927SAndroid Build Coastguard Worker
670*61046927SAndroid Build Coastguard Worker /* Also emit any necessary out-parameter conversions. */
671*61046927SAndroid Build Coastguard Worker instructions->append_list(&post_call_conversions);
672*61046927SAndroid Build Coastguard Worker
673*61046927SAndroid Build Coastguard Worker return deref ? deref->clone(ctx, NULL) : NULL;
674*61046927SAndroid Build Coastguard Worker }
675*61046927SAndroid Build Coastguard Worker
676*61046927SAndroid Build Coastguard Worker /**
677*61046927SAndroid Build Coastguard Worker * Given a function name and parameter list, find the matching signature.
678*61046927SAndroid Build Coastguard Worker */
679*61046927SAndroid Build Coastguard Worker static ir_function_signature *
match_function_by_name(const char * name,exec_list * actual_parameters,struct _mesa_glsl_parse_state * state)680*61046927SAndroid Build Coastguard Worker match_function_by_name(const char *name,
681*61046927SAndroid Build Coastguard Worker exec_list *actual_parameters,
682*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
683*61046927SAndroid Build Coastguard Worker {
684*61046927SAndroid Build Coastguard Worker ir_function *f = state->symbols->get_function(name);
685*61046927SAndroid Build Coastguard Worker ir_function_signature *local_sig = NULL;
686*61046927SAndroid Build Coastguard Worker ir_function_signature *sig = NULL;
687*61046927SAndroid Build Coastguard Worker
688*61046927SAndroid Build Coastguard Worker /* Is the function hidden by a record type constructor? */
689*61046927SAndroid Build Coastguard Worker if (state->symbols->get_type(name))
690*61046927SAndroid Build Coastguard Worker return sig; /* no match */
691*61046927SAndroid Build Coastguard Worker
692*61046927SAndroid Build Coastguard Worker /* Is the function hidden by a variable (impossible in 1.10)? */
693*61046927SAndroid Build Coastguard Worker if (!state->symbols->separate_function_namespace
694*61046927SAndroid Build Coastguard Worker && state->symbols->get_variable(name))
695*61046927SAndroid Build Coastguard Worker return sig; /* no match */
696*61046927SAndroid Build Coastguard Worker
697*61046927SAndroid Build Coastguard Worker if (f != NULL) {
698*61046927SAndroid Build Coastguard Worker /* In desktop GL, the presence of a user-defined signature hides any
699*61046927SAndroid Build Coastguard Worker * built-in signatures, so we must ignore them. In contrast, in ES2
700*61046927SAndroid Build Coastguard Worker * user-defined signatures add new overloads, so we must consider them.
701*61046927SAndroid Build Coastguard Worker */
702*61046927SAndroid Build Coastguard Worker bool allow_builtins = state->es_shader || !f->has_user_signature();
703*61046927SAndroid Build Coastguard Worker
704*61046927SAndroid Build Coastguard Worker /* Look for a match in the local shader. If exact, we're done. */
705*61046927SAndroid Build Coastguard Worker bool is_exact = false;
706*61046927SAndroid Build Coastguard Worker sig = local_sig = f->matching_signature(state, actual_parameters,
707*61046927SAndroid Build Coastguard Worker state->has_implicit_conversions(),
708*61046927SAndroid Build Coastguard Worker state->has_implicit_int_to_uint_conversion(),
709*61046927SAndroid Build Coastguard Worker allow_builtins, &is_exact);
710*61046927SAndroid Build Coastguard Worker if (is_exact)
711*61046927SAndroid Build Coastguard Worker return sig;
712*61046927SAndroid Build Coastguard Worker
713*61046927SAndroid Build Coastguard Worker if (!allow_builtins)
714*61046927SAndroid Build Coastguard Worker return sig;
715*61046927SAndroid Build Coastguard Worker }
716*61046927SAndroid Build Coastguard Worker
717*61046927SAndroid Build Coastguard Worker /* Local shader has no exact candidates; check the built-ins. */
718*61046927SAndroid Build Coastguard Worker sig = _mesa_glsl_find_builtin_function(state, name, actual_parameters);
719*61046927SAndroid Build Coastguard Worker
720*61046927SAndroid Build Coastguard Worker /* if _mesa_glsl_find_builtin_function failed, fall back to the result
721*61046927SAndroid Build Coastguard Worker * of choose_best_inexact_overload() instead. This should only affect
722*61046927SAndroid Build Coastguard Worker * GLES.
723*61046927SAndroid Build Coastguard Worker */
724*61046927SAndroid Build Coastguard Worker return sig ? sig : local_sig;
725*61046927SAndroid Build Coastguard Worker }
726*61046927SAndroid Build Coastguard Worker
727*61046927SAndroid Build Coastguard Worker static ir_function_signature *
match_subroutine_by_name(const char * name,exec_list * actual_parameters,struct _mesa_glsl_parse_state * state,ir_variable ** var_r)728*61046927SAndroid Build Coastguard Worker match_subroutine_by_name(const char *name,
729*61046927SAndroid Build Coastguard Worker exec_list *actual_parameters,
730*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state,
731*61046927SAndroid Build Coastguard Worker ir_variable **var_r)
732*61046927SAndroid Build Coastguard Worker {
733*61046927SAndroid Build Coastguard Worker void *ctx = state;
734*61046927SAndroid Build Coastguard Worker ir_function_signature *sig = NULL;
735*61046927SAndroid Build Coastguard Worker ir_function *f, *found = NULL;
736*61046927SAndroid Build Coastguard Worker const char *new_name;
737*61046927SAndroid Build Coastguard Worker ir_variable *var;
738*61046927SAndroid Build Coastguard Worker bool is_exact = false;
739*61046927SAndroid Build Coastguard Worker
740*61046927SAndroid Build Coastguard Worker new_name =
741*61046927SAndroid Build Coastguard Worker ralloc_asprintf(ctx, "%s_%s",
742*61046927SAndroid Build Coastguard Worker _mesa_shader_stage_to_subroutine_prefix(state->stage),
743*61046927SAndroid Build Coastguard Worker name);
744*61046927SAndroid Build Coastguard Worker var = state->symbols->get_variable(new_name);
745*61046927SAndroid Build Coastguard Worker if (!var)
746*61046927SAndroid Build Coastguard Worker return NULL;
747*61046927SAndroid Build Coastguard Worker
748*61046927SAndroid Build Coastguard Worker for (int i = 0; i < state->num_subroutine_types; i++) {
749*61046927SAndroid Build Coastguard Worker f = state->subroutine_types[i];
750*61046927SAndroid Build Coastguard Worker if (strcmp(f->name, glsl_get_type_name(glsl_without_array(var->type))))
751*61046927SAndroid Build Coastguard Worker continue;
752*61046927SAndroid Build Coastguard Worker found = f;
753*61046927SAndroid Build Coastguard Worker break;
754*61046927SAndroid Build Coastguard Worker }
755*61046927SAndroid Build Coastguard Worker
756*61046927SAndroid Build Coastguard Worker if (!found)
757*61046927SAndroid Build Coastguard Worker return NULL;
758*61046927SAndroid Build Coastguard Worker *var_r = var;
759*61046927SAndroid Build Coastguard Worker sig = found->matching_signature(state, actual_parameters,
760*61046927SAndroid Build Coastguard Worker state->has_implicit_conversions(),
761*61046927SAndroid Build Coastguard Worker state->has_implicit_int_to_uint_conversion(),
762*61046927SAndroid Build Coastguard Worker false, &is_exact);
763*61046927SAndroid Build Coastguard Worker return sig;
764*61046927SAndroid Build Coastguard Worker }
765*61046927SAndroid Build Coastguard Worker
766*61046927SAndroid Build Coastguard Worker static ir_rvalue *
generate_array_index(void * mem_ctx,exec_list * instructions,struct _mesa_glsl_parse_state * state,YYLTYPE loc,const ast_expression * array,ast_expression * idx,const char ** function_name,exec_list * actual_parameters)767*61046927SAndroid Build Coastguard Worker generate_array_index(void *mem_ctx, exec_list *instructions,
768*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state, YYLTYPE loc,
769*61046927SAndroid Build Coastguard Worker const ast_expression *array, ast_expression *idx,
770*61046927SAndroid Build Coastguard Worker const char **function_name, exec_list *actual_parameters)
771*61046927SAndroid Build Coastguard Worker {
772*61046927SAndroid Build Coastguard Worker if (array->oper == ast_array_index) {
773*61046927SAndroid Build Coastguard Worker /* This handles arrays of arrays */
774*61046927SAndroid Build Coastguard Worker ir_rvalue *outer_array = generate_array_index(mem_ctx, instructions,
775*61046927SAndroid Build Coastguard Worker state, loc,
776*61046927SAndroid Build Coastguard Worker array->subexpressions[0],
777*61046927SAndroid Build Coastguard Worker array->subexpressions[1],
778*61046927SAndroid Build Coastguard Worker function_name,
779*61046927SAndroid Build Coastguard Worker actual_parameters);
780*61046927SAndroid Build Coastguard Worker ir_rvalue *outer_array_idx = idx->hir(instructions, state);
781*61046927SAndroid Build Coastguard Worker
782*61046927SAndroid Build Coastguard Worker YYLTYPE index_loc = idx->get_location();
783*61046927SAndroid Build Coastguard Worker return _mesa_ast_array_index_to_hir(mem_ctx, state, outer_array,
784*61046927SAndroid Build Coastguard Worker outer_array_idx, loc,
785*61046927SAndroid Build Coastguard Worker index_loc);
786*61046927SAndroid Build Coastguard Worker } else {
787*61046927SAndroid Build Coastguard Worker ir_variable *sub_var = NULL;
788*61046927SAndroid Build Coastguard Worker *function_name = array->primary_expression.identifier;
789*61046927SAndroid Build Coastguard Worker
790*61046927SAndroid Build Coastguard Worker if (!match_subroutine_by_name(*function_name, actual_parameters,
791*61046927SAndroid Build Coastguard Worker state, &sub_var)) {
792*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "Unknown subroutine `%s'",
793*61046927SAndroid Build Coastguard Worker *function_name);
794*61046927SAndroid Build Coastguard Worker *function_name = NULL; /* indicate error condition to caller */
795*61046927SAndroid Build Coastguard Worker return NULL;
796*61046927SAndroid Build Coastguard Worker }
797*61046927SAndroid Build Coastguard Worker
798*61046927SAndroid Build Coastguard Worker ir_rvalue *outer_array_idx = idx->hir(instructions, state);
799*61046927SAndroid Build Coastguard Worker return new(mem_ctx) ir_dereference_array(sub_var, outer_array_idx);
800*61046927SAndroid Build Coastguard Worker }
801*61046927SAndroid Build Coastguard Worker }
802*61046927SAndroid Build Coastguard Worker
803*61046927SAndroid Build Coastguard Worker static bool
function_exists(_mesa_glsl_parse_state * state,struct glsl_symbol_table * symbols,const char * name)804*61046927SAndroid Build Coastguard Worker function_exists(_mesa_glsl_parse_state *state,
805*61046927SAndroid Build Coastguard Worker struct glsl_symbol_table *symbols, const char *name)
806*61046927SAndroid Build Coastguard Worker {
807*61046927SAndroid Build Coastguard Worker ir_function *f = symbols->get_function(name);
808*61046927SAndroid Build Coastguard Worker if (f != NULL) {
809*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_function_signature, sig, &f->signatures) {
810*61046927SAndroid Build Coastguard Worker if (sig->is_builtin() && !sig->is_builtin_available(state))
811*61046927SAndroid Build Coastguard Worker continue;
812*61046927SAndroid Build Coastguard Worker return true;
813*61046927SAndroid Build Coastguard Worker }
814*61046927SAndroid Build Coastguard Worker }
815*61046927SAndroid Build Coastguard Worker return false;
816*61046927SAndroid Build Coastguard Worker }
817*61046927SAndroid Build Coastguard Worker
818*61046927SAndroid Build Coastguard Worker static void
print_function_prototypes(_mesa_glsl_parse_state * state,YYLTYPE * loc,ir_function * f)819*61046927SAndroid Build Coastguard Worker print_function_prototypes(_mesa_glsl_parse_state *state, YYLTYPE *loc,
820*61046927SAndroid Build Coastguard Worker ir_function *f)
821*61046927SAndroid Build Coastguard Worker {
822*61046927SAndroid Build Coastguard Worker if (f == NULL)
823*61046927SAndroid Build Coastguard Worker return;
824*61046927SAndroid Build Coastguard Worker
825*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_function_signature, sig, &f->signatures) {
826*61046927SAndroid Build Coastguard Worker if (sig->is_builtin() && !sig->is_builtin_available(state))
827*61046927SAndroid Build Coastguard Worker continue;
828*61046927SAndroid Build Coastguard Worker
829*61046927SAndroid Build Coastguard Worker char *str = prototype_string(sig->return_type, f->name,
830*61046927SAndroid Build Coastguard Worker &sig->parameters);
831*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, " %s", str);
832*61046927SAndroid Build Coastguard Worker ralloc_free(str);
833*61046927SAndroid Build Coastguard Worker }
834*61046927SAndroid Build Coastguard Worker }
835*61046927SAndroid Build Coastguard Worker
836*61046927SAndroid Build Coastguard Worker /**
837*61046927SAndroid Build Coastguard Worker * Raise a "no matching function" error, listing all possible overloads the
838*61046927SAndroid Build Coastguard Worker * compiler considered so developers can figure out what went wrong.
839*61046927SAndroid Build Coastguard Worker */
840*61046927SAndroid Build Coastguard Worker static void
no_matching_function_error(const char * name,YYLTYPE * loc,exec_list * actual_parameters,_mesa_glsl_parse_state * state)841*61046927SAndroid Build Coastguard Worker no_matching_function_error(const char *name,
842*61046927SAndroid Build Coastguard Worker YYLTYPE *loc,
843*61046927SAndroid Build Coastguard Worker exec_list *actual_parameters,
844*61046927SAndroid Build Coastguard Worker _mesa_glsl_parse_state *state)
845*61046927SAndroid Build Coastguard Worker {
846*61046927SAndroid Build Coastguard Worker gl_shader *sh = _mesa_glsl_get_builtin_function_shader();
847*61046927SAndroid Build Coastguard Worker
848*61046927SAndroid Build Coastguard Worker if (!function_exists(state, state->symbols, name)
849*61046927SAndroid Build Coastguard Worker && (!state->uses_builtin_functions
850*61046927SAndroid Build Coastguard Worker || !function_exists(state, sh->symbols, name))) {
851*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "no function with name '%s'", name);
852*61046927SAndroid Build Coastguard Worker } else {
853*61046927SAndroid Build Coastguard Worker char *str = prototype_string(NULL, name, actual_parameters);
854*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
855*61046927SAndroid Build Coastguard Worker "no matching function for call to `%s';"
856*61046927SAndroid Build Coastguard Worker " candidates are:",
857*61046927SAndroid Build Coastguard Worker str);
858*61046927SAndroid Build Coastguard Worker ralloc_free(str);
859*61046927SAndroid Build Coastguard Worker
860*61046927SAndroid Build Coastguard Worker print_function_prototypes(state, loc,
861*61046927SAndroid Build Coastguard Worker state->symbols->get_function(name));
862*61046927SAndroid Build Coastguard Worker
863*61046927SAndroid Build Coastguard Worker if (state->uses_builtin_functions) {
864*61046927SAndroid Build Coastguard Worker print_function_prototypes(state, loc,
865*61046927SAndroid Build Coastguard Worker sh->symbols->get_function(name));
866*61046927SAndroid Build Coastguard Worker }
867*61046927SAndroid Build Coastguard Worker }
868*61046927SAndroid Build Coastguard Worker }
869*61046927SAndroid Build Coastguard Worker
870*61046927SAndroid Build Coastguard Worker /**
871*61046927SAndroid Build Coastguard Worker * Perform automatic type conversion of constructor parameters
872*61046927SAndroid Build Coastguard Worker *
873*61046927SAndroid Build Coastguard Worker * This implements the rules in the "Conversion and Scalar Constructors"
874*61046927SAndroid Build Coastguard Worker * section (GLSL 1.10 section 5.4.1), not the "Implicit Conversions" rules.
875*61046927SAndroid Build Coastguard Worker */
876*61046927SAndroid Build Coastguard Worker static ir_rvalue *
convert_component(ir_rvalue * src,const glsl_type * desired_type)877*61046927SAndroid Build Coastguard Worker convert_component(ir_rvalue *src, const glsl_type *desired_type)
878*61046927SAndroid Build Coastguard Worker {
879*61046927SAndroid Build Coastguard Worker void *ctx = ralloc_parent(src);
880*61046927SAndroid Build Coastguard Worker const unsigned a = desired_type->base_type;
881*61046927SAndroid Build Coastguard Worker const unsigned b = src->type->base_type;
882*61046927SAndroid Build Coastguard Worker ir_expression *result = NULL;
883*61046927SAndroid Build Coastguard Worker
884*61046927SAndroid Build Coastguard Worker if (glsl_type_is_error(src->type))
885*61046927SAndroid Build Coastguard Worker return src;
886*61046927SAndroid Build Coastguard Worker
887*61046927SAndroid Build Coastguard Worker assert(a <= GLSL_TYPE_IMAGE);
888*61046927SAndroid Build Coastguard Worker assert(b <= GLSL_TYPE_IMAGE);
889*61046927SAndroid Build Coastguard Worker
890*61046927SAndroid Build Coastguard Worker if (a == b)
891*61046927SAndroid Build Coastguard Worker return src;
892*61046927SAndroid Build Coastguard Worker
893*61046927SAndroid Build Coastguard Worker switch (a) {
894*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
895*61046927SAndroid Build Coastguard Worker switch (b) {
896*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
897*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2u, src);
898*61046927SAndroid Build Coastguard Worker break;
899*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
900*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f162u, src);
901*61046927SAndroid Build Coastguard Worker break;
902*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
903*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2u, src);
904*61046927SAndroid Build Coastguard Worker break;
905*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
906*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2u,
907*61046927SAndroid Build Coastguard Worker new(ctx) ir_expression(ir_unop_b2i,
908*61046927SAndroid Build Coastguard Worker src));
909*61046927SAndroid Build Coastguard Worker break;
910*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
911*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_d2u, src);
912*61046927SAndroid Build Coastguard Worker break;
913*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
914*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u642u, src);
915*61046927SAndroid Build Coastguard Worker break;
916*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
917*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642u, src);
918*61046927SAndroid Build Coastguard Worker break;
919*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_SAMPLER:
920*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_unpack_sampler_2x32, src);
921*61046927SAndroid Build Coastguard Worker break;
922*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_IMAGE:
923*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_unpack_image_2x32, src);
924*61046927SAndroid Build Coastguard Worker break;
925*61046927SAndroid Build Coastguard Worker }
926*61046927SAndroid Build Coastguard Worker break;
927*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
928*61046927SAndroid Build Coastguard Worker switch (b) {
929*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
930*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u2i, src);
931*61046927SAndroid Build Coastguard Worker break;
932*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
933*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f162i, src);
934*61046927SAndroid Build Coastguard Worker break;
935*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
936*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2i, src);
937*61046927SAndroid Build Coastguard Worker break;
938*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
939*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_b2i, src);
940*61046927SAndroid Build Coastguard Worker break;
941*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
942*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_d2i, src);
943*61046927SAndroid Build Coastguard Worker break;
944*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
945*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u642i, src);
946*61046927SAndroid Build Coastguard Worker break;
947*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
948*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642i, src);
949*61046927SAndroid Build Coastguard Worker break;
950*61046927SAndroid Build Coastguard Worker }
951*61046927SAndroid Build Coastguard Worker break;
952*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
953*61046927SAndroid Build Coastguard Worker switch (b) {
954*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
955*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u2f16, desired_type, src, NULL);
956*61046927SAndroid Build Coastguard Worker break;
957*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
958*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2f16, desired_type, src, NULL);
959*61046927SAndroid Build Coastguard Worker break;
960*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
961*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_b2f16, desired_type, src, NULL);
962*61046927SAndroid Build Coastguard Worker break;
963*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
964*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2f16, desired_type, src, NULL);
965*61046927SAndroid Build Coastguard Worker break;
966*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
967*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_d2f16, desired_type, src, NULL);
968*61046927SAndroid Build Coastguard Worker break;
969*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
970*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u642f16, desired_type, src, NULL);
971*61046927SAndroid Build Coastguard Worker break;
972*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
973*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642f16, desired_type, src, NULL);
974*61046927SAndroid Build Coastguard Worker break;
975*61046927SAndroid Build Coastguard Worker }
976*61046927SAndroid Build Coastguard Worker break;
977*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
978*61046927SAndroid Build Coastguard Worker switch (b) {
979*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
980*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u2f, desired_type, src, NULL);
981*61046927SAndroid Build Coastguard Worker break;
982*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
983*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2f, desired_type, src, NULL);
984*61046927SAndroid Build Coastguard Worker break;
985*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
986*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_b2f, desired_type, src, NULL);
987*61046927SAndroid Build Coastguard Worker break;
988*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
989*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f162f, desired_type, src, NULL);
990*61046927SAndroid Build Coastguard Worker break;
991*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
992*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_d2f, desired_type, src, NULL);
993*61046927SAndroid Build Coastguard Worker break;
994*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
995*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u642f, desired_type, src, NULL);
996*61046927SAndroid Build Coastguard Worker break;
997*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
998*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642f, desired_type, src, NULL);
999*61046927SAndroid Build Coastguard Worker break;
1000*61046927SAndroid Build Coastguard Worker }
1001*61046927SAndroid Build Coastguard Worker break;
1002*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
1003*61046927SAndroid Build Coastguard Worker switch (b) {
1004*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
1005*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2b,
1006*61046927SAndroid Build Coastguard Worker new(ctx) ir_expression(ir_unop_u2i,
1007*61046927SAndroid Build Coastguard Worker src));
1008*61046927SAndroid Build Coastguard Worker break;
1009*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
1010*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2b, desired_type, src, NULL);
1011*61046927SAndroid Build Coastguard Worker break;
1012*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
1013*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f162b, desired_type, src, NULL);
1014*61046927SAndroid Build Coastguard Worker break;
1015*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
1016*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2b, desired_type, src, NULL);
1017*61046927SAndroid Build Coastguard Worker break;
1018*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
1019*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_d2b, desired_type, src, NULL);
1020*61046927SAndroid Build Coastguard Worker break;
1021*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
1022*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642b,
1023*61046927SAndroid Build Coastguard Worker new(ctx) ir_expression(ir_unop_u642i64,
1024*61046927SAndroid Build Coastguard Worker src));
1025*61046927SAndroid Build Coastguard Worker break;
1026*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
1027*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642b, desired_type, src, NULL);
1028*61046927SAndroid Build Coastguard Worker break;
1029*61046927SAndroid Build Coastguard Worker }
1030*61046927SAndroid Build Coastguard Worker break;
1031*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
1032*61046927SAndroid Build Coastguard Worker switch (b) {
1033*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
1034*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2d, src);
1035*61046927SAndroid Build Coastguard Worker break;
1036*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
1037*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u2d, src);
1038*61046927SAndroid Build Coastguard Worker break;
1039*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
1040*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2d,
1041*61046927SAndroid Build Coastguard Worker new(ctx) ir_expression(ir_unop_b2f,
1042*61046927SAndroid Build Coastguard Worker src));
1043*61046927SAndroid Build Coastguard Worker break;
1044*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
1045*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f162d, desired_type, src, NULL);
1046*61046927SAndroid Build Coastguard Worker break;
1047*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
1048*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2d, desired_type, src, NULL);
1049*61046927SAndroid Build Coastguard Worker break;
1050*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
1051*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u642d, desired_type, src, NULL);
1052*61046927SAndroid Build Coastguard Worker break;
1053*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
1054*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642d, desired_type, src, NULL);
1055*61046927SAndroid Build Coastguard Worker break;
1056*61046927SAndroid Build Coastguard Worker }
1057*61046927SAndroid Build Coastguard Worker break;
1058*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
1059*61046927SAndroid Build Coastguard Worker switch (b) {
1060*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
1061*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2u64, src);
1062*61046927SAndroid Build Coastguard Worker break;
1063*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
1064*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u2u64, src);
1065*61046927SAndroid Build Coastguard Worker break;
1066*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
1067*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642u64,
1068*61046927SAndroid Build Coastguard Worker new(ctx) ir_expression(ir_unop_b2i64,
1069*61046927SAndroid Build Coastguard Worker src));
1070*61046927SAndroid Build Coastguard Worker break;
1071*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
1072*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f162u64, src);
1073*61046927SAndroid Build Coastguard Worker break;
1074*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
1075*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2u64, src);
1076*61046927SAndroid Build Coastguard Worker break;
1077*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
1078*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_d2u64, src);
1079*61046927SAndroid Build Coastguard Worker break;
1080*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
1081*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i642u64, src);
1082*61046927SAndroid Build Coastguard Worker break;
1083*61046927SAndroid Build Coastguard Worker }
1084*61046927SAndroid Build Coastguard Worker break;
1085*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
1086*61046927SAndroid Build Coastguard Worker switch (b) {
1087*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
1088*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_i2i64, src);
1089*61046927SAndroid Build Coastguard Worker break;
1090*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
1091*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u2i64, src);
1092*61046927SAndroid Build Coastguard Worker break;
1093*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
1094*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_b2i64, src);
1095*61046927SAndroid Build Coastguard Worker break;
1096*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT16:
1097*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f162i64, src);
1098*61046927SAndroid Build Coastguard Worker break;
1099*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
1100*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_f2i64, src);
1101*61046927SAndroid Build Coastguard Worker break;
1102*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
1103*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_d2i64, src);
1104*61046927SAndroid Build Coastguard Worker break;
1105*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
1106*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_expression(ir_unop_u642i64, src);
1107*61046927SAndroid Build Coastguard Worker break;
1108*61046927SAndroid Build Coastguard Worker }
1109*61046927SAndroid Build Coastguard Worker break;
1110*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_SAMPLER:
1111*61046927SAndroid Build Coastguard Worker switch (b) {
1112*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
1113*61046927SAndroid Build Coastguard Worker result = new(ctx)
1114*61046927SAndroid Build Coastguard Worker ir_expression(ir_unop_pack_sampler_2x32, desired_type, src);
1115*61046927SAndroid Build Coastguard Worker break;
1116*61046927SAndroid Build Coastguard Worker }
1117*61046927SAndroid Build Coastguard Worker break;
1118*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_IMAGE:
1119*61046927SAndroid Build Coastguard Worker switch (b) {
1120*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
1121*61046927SAndroid Build Coastguard Worker result = new(ctx)
1122*61046927SAndroid Build Coastguard Worker ir_expression(ir_unop_pack_image_2x32, desired_type, src);
1123*61046927SAndroid Build Coastguard Worker break;
1124*61046927SAndroid Build Coastguard Worker }
1125*61046927SAndroid Build Coastguard Worker break;
1126*61046927SAndroid Build Coastguard Worker }
1127*61046927SAndroid Build Coastguard Worker
1128*61046927SAndroid Build Coastguard Worker assert(result != NULL);
1129*61046927SAndroid Build Coastguard Worker assert(result->type == desired_type);
1130*61046927SAndroid Build Coastguard Worker
1131*61046927SAndroid Build Coastguard Worker /* Try constant folding; it may fold in the conversion we just added. */
1132*61046927SAndroid Build Coastguard Worker ir_constant *const constant = result->constant_expression_value(ctx);
1133*61046927SAndroid Build Coastguard Worker return (constant != NULL) ? (ir_rvalue *) constant : (ir_rvalue *) result;
1134*61046927SAndroid Build Coastguard Worker }
1135*61046927SAndroid Build Coastguard Worker
1136*61046927SAndroid Build Coastguard Worker
1137*61046927SAndroid Build Coastguard Worker /**
1138*61046927SAndroid Build Coastguard Worker * Perform automatic type and constant conversion of constructor parameters
1139*61046927SAndroid Build Coastguard Worker *
1140*61046927SAndroid Build Coastguard Worker * This implements the rules in the "Implicit Conversions" rules, not the
1141*61046927SAndroid Build Coastguard Worker * "Conversion and Scalar Constructors".
1142*61046927SAndroid Build Coastguard Worker *
1143*61046927SAndroid Build Coastguard Worker * After attempting the implicit conversion, an attempt to convert into a
1144*61046927SAndroid Build Coastguard Worker * constant valued expression is also done.
1145*61046927SAndroid Build Coastguard Worker *
1146*61046927SAndroid Build Coastguard Worker * The \c from \c ir_rvalue is converted "in place".
1147*61046927SAndroid Build Coastguard Worker *
1148*61046927SAndroid Build Coastguard Worker * \param from Operand that is being converted
1149*61046927SAndroid Build Coastguard Worker * \param to Base type the operand will be converted to
1150*61046927SAndroid Build Coastguard Worker * \param state GLSL compiler state
1151*61046927SAndroid Build Coastguard Worker *
1152*61046927SAndroid Build Coastguard Worker * \return
1153*61046927SAndroid Build Coastguard Worker * If the attempt to convert into a constant expression succeeds, \c true is
1154*61046927SAndroid Build Coastguard Worker * returned. Otherwise \c false is returned.
1155*61046927SAndroid Build Coastguard Worker */
1156*61046927SAndroid Build Coastguard Worker static bool
implicitly_convert_component(ir_rvalue * & from,const glsl_base_type to,struct _mesa_glsl_parse_state * state)1157*61046927SAndroid Build Coastguard Worker implicitly_convert_component(ir_rvalue * &from, const glsl_base_type to,
1158*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
1159*61046927SAndroid Build Coastguard Worker {
1160*61046927SAndroid Build Coastguard Worker void *mem_ctx = state;
1161*61046927SAndroid Build Coastguard Worker ir_rvalue *result = from;
1162*61046927SAndroid Build Coastguard Worker
1163*61046927SAndroid Build Coastguard Worker if (to != from->type->base_type) {
1164*61046927SAndroid Build Coastguard Worker const glsl_type *desired_type =
1165*61046927SAndroid Build Coastguard Worker glsl_simple_type(to,
1166*61046927SAndroid Build Coastguard Worker from->type->vector_elements,
1167*61046927SAndroid Build Coastguard Worker from->type->matrix_columns);
1168*61046927SAndroid Build Coastguard Worker
1169*61046927SAndroid Build Coastguard Worker if (_mesa_glsl_can_implicitly_convert(from->type, desired_type,
1170*61046927SAndroid Build Coastguard Worker state->has_implicit_conversions(),
1171*61046927SAndroid Build Coastguard Worker state->has_implicit_int_to_uint_conversion())) {
1172*61046927SAndroid Build Coastguard Worker /* Even though convert_component() implements the constructor
1173*61046927SAndroid Build Coastguard Worker * conversion rules (not the implicit conversion rules), its safe
1174*61046927SAndroid Build Coastguard Worker * to use it here because we already checked that the implicit
1175*61046927SAndroid Build Coastguard Worker * conversion is legal.
1176*61046927SAndroid Build Coastguard Worker */
1177*61046927SAndroid Build Coastguard Worker result = convert_component(from, desired_type);
1178*61046927SAndroid Build Coastguard Worker }
1179*61046927SAndroid Build Coastguard Worker }
1180*61046927SAndroid Build Coastguard Worker
1181*61046927SAndroid Build Coastguard Worker ir_rvalue *const constant = result->constant_expression_value(mem_ctx);
1182*61046927SAndroid Build Coastguard Worker
1183*61046927SAndroid Build Coastguard Worker if (constant != NULL)
1184*61046927SAndroid Build Coastguard Worker result = constant;
1185*61046927SAndroid Build Coastguard Worker
1186*61046927SAndroid Build Coastguard Worker if (from != result) {
1187*61046927SAndroid Build Coastguard Worker from->replace_with(result);
1188*61046927SAndroid Build Coastguard Worker from = result;
1189*61046927SAndroid Build Coastguard Worker }
1190*61046927SAndroid Build Coastguard Worker
1191*61046927SAndroid Build Coastguard Worker return constant != NULL;
1192*61046927SAndroid Build Coastguard Worker }
1193*61046927SAndroid Build Coastguard Worker
1194*61046927SAndroid Build Coastguard Worker
1195*61046927SAndroid Build Coastguard Worker /**
1196*61046927SAndroid Build Coastguard Worker * Dereference a specific component from a scalar, vector, or matrix
1197*61046927SAndroid Build Coastguard Worker */
1198*61046927SAndroid Build Coastguard Worker static ir_rvalue *
dereference_component(ir_rvalue * src,unsigned component)1199*61046927SAndroid Build Coastguard Worker dereference_component(ir_rvalue *src, unsigned component)
1200*61046927SAndroid Build Coastguard Worker {
1201*61046927SAndroid Build Coastguard Worker void *ctx = ralloc_parent(src);
1202*61046927SAndroid Build Coastguard Worker assert(component < glsl_get_components(src->type));
1203*61046927SAndroid Build Coastguard Worker
1204*61046927SAndroid Build Coastguard Worker /* If the source is a constant, just create a new constant instead of a
1205*61046927SAndroid Build Coastguard Worker * dereference of the existing constant.
1206*61046927SAndroid Build Coastguard Worker */
1207*61046927SAndroid Build Coastguard Worker ir_constant *constant = src->as_constant();
1208*61046927SAndroid Build Coastguard Worker if (constant)
1209*61046927SAndroid Build Coastguard Worker return new(ctx) ir_constant(constant, component);
1210*61046927SAndroid Build Coastguard Worker
1211*61046927SAndroid Build Coastguard Worker if (glsl_type_is_scalar(src->type)) {
1212*61046927SAndroid Build Coastguard Worker return src;
1213*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_vector(src->type)) {
1214*61046927SAndroid Build Coastguard Worker return new(ctx) ir_swizzle(src, component, 0, 0, 0, 1);
1215*61046927SAndroid Build Coastguard Worker } else {
1216*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_matrix(src->type));
1217*61046927SAndroid Build Coastguard Worker
1218*61046927SAndroid Build Coastguard Worker /* Dereference a row of the matrix, then call this function again to get
1219*61046927SAndroid Build Coastguard Worker * a specific element from that row.
1220*61046927SAndroid Build Coastguard Worker */
1221*61046927SAndroid Build Coastguard Worker const int c = component / glsl_get_column_type(src->type)->vector_elements;
1222*61046927SAndroid Build Coastguard Worker const int r = component % glsl_get_column_type(src->type)->vector_elements;
1223*61046927SAndroid Build Coastguard Worker ir_constant *const col_index = new(ctx) ir_constant(c);
1224*61046927SAndroid Build Coastguard Worker ir_dereference *const col = new(ctx) ir_dereference_array(src,
1225*61046927SAndroid Build Coastguard Worker col_index);
1226*61046927SAndroid Build Coastguard Worker
1227*61046927SAndroid Build Coastguard Worker col->type = glsl_get_column_type(src->type);
1228*61046927SAndroid Build Coastguard Worker
1229*61046927SAndroid Build Coastguard Worker return dereference_component(col, r);
1230*61046927SAndroid Build Coastguard Worker }
1231*61046927SAndroid Build Coastguard Worker
1232*61046927SAndroid Build Coastguard Worker assert(!"Should not get here.");
1233*61046927SAndroid Build Coastguard Worker return NULL;
1234*61046927SAndroid Build Coastguard Worker }
1235*61046927SAndroid Build Coastguard Worker
1236*61046927SAndroid Build Coastguard Worker
1237*61046927SAndroid Build Coastguard Worker static ir_rvalue *
process_vec_mat_constructor(exec_list * instructions,const glsl_type * constructor_type,YYLTYPE * loc,exec_list * parameters,struct _mesa_glsl_parse_state * state)1238*61046927SAndroid Build Coastguard Worker process_vec_mat_constructor(exec_list *instructions,
1239*61046927SAndroid Build Coastguard Worker const glsl_type *constructor_type,
1240*61046927SAndroid Build Coastguard Worker YYLTYPE *loc, exec_list *parameters,
1241*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
1242*61046927SAndroid Build Coastguard Worker {
1243*61046927SAndroid Build Coastguard Worker void *ctx = state;
1244*61046927SAndroid Build Coastguard Worker
1245*61046927SAndroid Build Coastguard Worker /* The ARB_shading_language_420pack spec says:
1246*61046927SAndroid Build Coastguard Worker *
1247*61046927SAndroid Build Coastguard Worker * "If an initializer is a list of initializers enclosed in curly braces,
1248*61046927SAndroid Build Coastguard Worker * the variable being declared must be a vector, a matrix, an array, or a
1249*61046927SAndroid Build Coastguard Worker * structure.
1250*61046927SAndroid Build Coastguard Worker *
1251*61046927SAndroid Build Coastguard Worker * int i = { 1 }; // illegal, i is not an aggregate"
1252*61046927SAndroid Build Coastguard Worker */
1253*61046927SAndroid Build Coastguard Worker if (constructor_type->vector_elements <= 1) {
1254*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "aggregates can only initialize vectors, "
1255*61046927SAndroid Build Coastguard Worker "matrices, arrays, and structs");
1256*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
1257*61046927SAndroid Build Coastguard Worker }
1258*61046927SAndroid Build Coastguard Worker
1259*61046927SAndroid Build Coastguard Worker exec_list actual_parameters;
1260*61046927SAndroid Build Coastguard Worker const unsigned parameter_count =
1261*61046927SAndroid Build Coastguard Worker process_parameters(instructions, &actual_parameters, parameters, state);
1262*61046927SAndroid Build Coastguard Worker
1263*61046927SAndroid Build Coastguard Worker if (parameter_count == 0
1264*61046927SAndroid Build Coastguard Worker || (glsl_type_is_vector(constructor_type) &&
1265*61046927SAndroid Build Coastguard Worker constructor_type->vector_elements != parameter_count)
1266*61046927SAndroid Build Coastguard Worker || (glsl_type_is_matrix(constructor_type) &&
1267*61046927SAndroid Build Coastguard Worker constructor_type->matrix_columns != parameter_count)) {
1268*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "%s constructor must have %u parameters",
1269*61046927SAndroid Build Coastguard Worker glsl_type_is_vector(constructor_type) ? "vector" : "matrix",
1270*61046927SAndroid Build Coastguard Worker constructor_type->vector_elements);
1271*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
1272*61046927SAndroid Build Coastguard Worker }
1273*61046927SAndroid Build Coastguard Worker
1274*61046927SAndroid Build Coastguard Worker bool all_parameters_are_constant = true;
1275*61046927SAndroid Build Coastguard Worker
1276*61046927SAndroid Build Coastguard Worker /* Type cast each parameter and, if possible, fold constants. */
1277*61046927SAndroid Build Coastguard Worker foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
1278*61046927SAndroid Build Coastguard Worker /* Apply implicit conversions (not the scalar constructor rules, see the
1279*61046927SAndroid Build Coastguard Worker * spec quote above!) and attempt to convert the parameter to a constant
1280*61046927SAndroid Build Coastguard Worker * valued expression. After doing so, track whether or not all the
1281*61046927SAndroid Build Coastguard Worker * parameters to the constructor are trivially constant valued
1282*61046927SAndroid Build Coastguard Worker * expressions.
1283*61046927SAndroid Build Coastguard Worker */
1284*61046927SAndroid Build Coastguard Worker all_parameters_are_constant &=
1285*61046927SAndroid Build Coastguard Worker implicitly_convert_component(ir, constructor_type->base_type, state);
1286*61046927SAndroid Build Coastguard Worker
1287*61046927SAndroid Build Coastguard Worker if (glsl_type_is_matrix(constructor_type)) {
1288*61046927SAndroid Build Coastguard Worker if (ir->type != glsl_get_column_type(constructor_type)) {
1289*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "type error in matrix constructor: "
1290*61046927SAndroid Build Coastguard Worker "expected: %s, found %s",
1291*61046927SAndroid Build Coastguard Worker glsl_get_type_name(glsl_get_column_type(constructor_type)),
1292*61046927SAndroid Build Coastguard Worker glsl_get_type_name(ir->type));
1293*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
1294*61046927SAndroid Build Coastguard Worker }
1295*61046927SAndroid Build Coastguard Worker } else if (ir->type != glsl_get_scalar_type(constructor_type)) {
1296*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "type error in vector constructor: "
1297*61046927SAndroid Build Coastguard Worker "expected: %s, found %s",
1298*61046927SAndroid Build Coastguard Worker glsl_get_type_name(glsl_get_scalar_type(constructor_type)),
1299*61046927SAndroid Build Coastguard Worker glsl_get_type_name(ir->type));
1300*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
1301*61046927SAndroid Build Coastguard Worker }
1302*61046927SAndroid Build Coastguard Worker }
1303*61046927SAndroid Build Coastguard Worker
1304*61046927SAndroid Build Coastguard Worker if (all_parameters_are_constant)
1305*61046927SAndroid Build Coastguard Worker return new(ctx) ir_constant(constructor_type, &actual_parameters);
1306*61046927SAndroid Build Coastguard Worker
1307*61046927SAndroid Build Coastguard Worker ir_variable *var = new(ctx) ir_variable(constructor_type, "vec_mat_ctor",
1308*61046927SAndroid Build Coastguard Worker ir_var_temporary);
1309*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
1310*61046927SAndroid Build Coastguard Worker
1311*61046927SAndroid Build Coastguard Worker int i = 0;
1312*61046927SAndroid Build Coastguard Worker
1313*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_rvalue, rhs, &actual_parameters) {
1314*61046927SAndroid Build Coastguard Worker ir_instruction *assignment = NULL;
1315*61046927SAndroid Build Coastguard Worker
1316*61046927SAndroid Build Coastguard Worker if (glsl_type_is_matrix(var->type)) {
1317*61046927SAndroid Build Coastguard Worker ir_rvalue *lhs =
1318*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i));
1319*61046927SAndroid Build Coastguard Worker assignment = new(ctx) ir_assignment(lhs, rhs);
1320*61046927SAndroid Build Coastguard Worker } else {
1321*61046927SAndroid Build Coastguard Worker /* use writemask rather than index for vector */
1322*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_vector(var->type));
1323*61046927SAndroid Build Coastguard Worker assert(i < 4);
1324*61046927SAndroid Build Coastguard Worker ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
1325*61046927SAndroid Build Coastguard Worker assignment = new(ctx) ir_assignment(lhs, rhs, 1u << i);
1326*61046927SAndroid Build Coastguard Worker }
1327*61046927SAndroid Build Coastguard Worker
1328*61046927SAndroid Build Coastguard Worker instructions->push_tail(assignment);
1329*61046927SAndroid Build Coastguard Worker
1330*61046927SAndroid Build Coastguard Worker i++;
1331*61046927SAndroid Build Coastguard Worker }
1332*61046927SAndroid Build Coastguard Worker
1333*61046927SAndroid Build Coastguard Worker return new(ctx) ir_dereference_variable(var);
1334*61046927SAndroid Build Coastguard Worker }
1335*61046927SAndroid Build Coastguard Worker
1336*61046927SAndroid Build Coastguard Worker
1337*61046927SAndroid Build Coastguard Worker static ir_rvalue *
process_array_constructor(exec_list * instructions,const glsl_type * constructor_type,YYLTYPE * loc,exec_list * parameters,struct _mesa_glsl_parse_state * state)1338*61046927SAndroid Build Coastguard Worker process_array_constructor(exec_list *instructions,
1339*61046927SAndroid Build Coastguard Worker const glsl_type *constructor_type,
1340*61046927SAndroid Build Coastguard Worker YYLTYPE *loc, exec_list *parameters,
1341*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
1342*61046927SAndroid Build Coastguard Worker {
1343*61046927SAndroid Build Coastguard Worker void *ctx = state;
1344*61046927SAndroid Build Coastguard Worker /* Array constructors come in two forms: sized and unsized. Sized array
1345*61046927SAndroid Build Coastguard Worker * constructors look like 'vec4[2](a, b)', where 'a' and 'b' are vec4
1346*61046927SAndroid Build Coastguard Worker * variables. In this case the number of parameters must exactly match the
1347*61046927SAndroid Build Coastguard Worker * specified size of the array.
1348*61046927SAndroid Build Coastguard Worker *
1349*61046927SAndroid Build Coastguard Worker * Unsized array constructors look like 'vec4[](a, b)', where 'a' and 'b'
1350*61046927SAndroid Build Coastguard Worker * are vec4 variables. In this case the size of the array being constructed
1351*61046927SAndroid Build Coastguard Worker * is determined by the number of parameters.
1352*61046927SAndroid Build Coastguard Worker *
1353*61046927SAndroid Build Coastguard Worker * From page 52 (page 58 of the PDF) of the GLSL 1.50 spec:
1354*61046927SAndroid Build Coastguard Worker *
1355*61046927SAndroid Build Coastguard Worker * "There must be exactly the same number of arguments as the size of
1356*61046927SAndroid Build Coastguard Worker * the array being constructed. If no size is present in the
1357*61046927SAndroid Build Coastguard Worker * constructor, then the array is explicitly sized to the number of
1358*61046927SAndroid Build Coastguard Worker * arguments provided. The arguments are assigned in order, starting at
1359*61046927SAndroid Build Coastguard Worker * element 0, to the elements of the constructed array. Each argument
1360*61046927SAndroid Build Coastguard Worker * must be the same type as the element type of the array, or be a type
1361*61046927SAndroid Build Coastguard Worker * that can be converted to the element type of the array according to
1362*61046927SAndroid Build Coastguard Worker * Section 4.1.10 "Implicit Conversions.""
1363*61046927SAndroid Build Coastguard Worker */
1364*61046927SAndroid Build Coastguard Worker exec_list actual_parameters;
1365*61046927SAndroid Build Coastguard Worker const unsigned parameter_count =
1366*61046927SAndroid Build Coastguard Worker process_parameters(instructions, &actual_parameters, parameters, state);
1367*61046927SAndroid Build Coastguard Worker bool is_unsized_array = glsl_type_is_unsized_array(constructor_type);
1368*61046927SAndroid Build Coastguard Worker
1369*61046927SAndroid Build Coastguard Worker if ((parameter_count == 0) ||
1370*61046927SAndroid Build Coastguard Worker (!is_unsized_array && (constructor_type->length != parameter_count))) {
1371*61046927SAndroid Build Coastguard Worker const unsigned min_param = is_unsized_array
1372*61046927SAndroid Build Coastguard Worker ? 1 : constructor_type->length;
1373*61046927SAndroid Build Coastguard Worker
1374*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "array constructor must have %s %u "
1375*61046927SAndroid Build Coastguard Worker "parameter%s",
1376*61046927SAndroid Build Coastguard Worker is_unsized_array ? "at least" : "exactly",
1377*61046927SAndroid Build Coastguard Worker min_param, (min_param <= 1) ? "" : "s");
1378*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
1379*61046927SAndroid Build Coastguard Worker }
1380*61046927SAndroid Build Coastguard Worker
1381*61046927SAndroid Build Coastguard Worker if (is_unsized_array) {
1382*61046927SAndroid Build Coastguard Worker constructor_type =
1383*61046927SAndroid Build Coastguard Worker glsl_array_type(constructor_type->fields.array,
1384*61046927SAndroid Build Coastguard Worker parameter_count, 0);
1385*61046927SAndroid Build Coastguard Worker assert(constructor_type != NULL);
1386*61046927SAndroid Build Coastguard Worker assert(constructor_type->length == parameter_count);
1387*61046927SAndroid Build Coastguard Worker }
1388*61046927SAndroid Build Coastguard Worker
1389*61046927SAndroid Build Coastguard Worker bool all_parameters_are_constant = true;
1390*61046927SAndroid Build Coastguard Worker const glsl_type *element_type = constructor_type->fields.array;
1391*61046927SAndroid Build Coastguard Worker
1392*61046927SAndroid Build Coastguard Worker /* Type cast each parameter and, if possible, fold constants. */
1393*61046927SAndroid Build Coastguard Worker foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
1394*61046927SAndroid Build Coastguard Worker /* Apply implicit conversions (not the scalar constructor rules, see the
1395*61046927SAndroid Build Coastguard Worker * spec quote above!) and attempt to convert the parameter to a constant
1396*61046927SAndroid Build Coastguard Worker * valued expression. After doing so, track whether or not all the
1397*61046927SAndroid Build Coastguard Worker * parameters to the constructor are trivially constant valued
1398*61046927SAndroid Build Coastguard Worker * expressions.
1399*61046927SAndroid Build Coastguard Worker */
1400*61046927SAndroid Build Coastguard Worker all_parameters_are_constant &=
1401*61046927SAndroid Build Coastguard Worker implicitly_convert_component(ir, element_type->base_type, state);
1402*61046927SAndroid Build Coastguard Worker
1403*61046927SAndroid Build Coastguard Worker if (glsl_type_is_unsized_array(constructor_type->fields.array)) {
1404*61046927SAndroid Build Coastguard Worker /* As the inner parameters of the constructor are created without
1405*61046927SAndroid Build Coastguard Worker * knowledge of each other we need to check to make sure unsized
1406*61046927SAndroid Build Coastguard Worker * parameters of unsized constructors all end up with the same size.
1407*61046927SAndroid Build Coastguard Worker *
1408*61046927SAndroid Build Coastguard Worker * e.g we make sure to fail for a constructor like this:
1409*61046927SAndroid Build Coastguard Worker * vec4[][] a = vec4[][](vec4[](vec4(0.0), vec4(1.0)),
1410*61046927SAndroid Build Coastguard Worker * vec4[](vec4(0.0), vec4(1.0), vec4(1.0)),
1411*61046927SAndroid Build Coastguard Worker * vec4[](vec4(0.0), vec4(1.0)));
1412*61046927SAndroid Build Coastguard Worker */
1413*61046927SAndroid Build Coastguard Worker if (glsl_type_is_unsized_array(element_type)) {
1414*61046927SAndroid Build Coastguard Worker /* This is the first parameter so just get the type */
1415*61046927SAndroid Build Coastguard Worker element_type = ir->type;
1416*61046927SAndroid Build Coastguard Worker } else if (element_type != ir->type) {
1417*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "type error in array constructor: "
1418*61046927SAndroid Build Coastguard Worker "expected: %s, found %s",
1419*61046927SAndroid Build Coastguard Worker glsl_get_type_name(element_type),
1420*61046927SAndroid Build Coastguard Worker glsl_get_type_name(ir->type));
1421*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
1422*61046927SAndroid Build Coastguard Worker }
1423*61046927SAndroid Build Coastguard Worker } else if (ir->type != constructor_type->fields.array) {
1424*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state, "type error in array constructor: "
1425*61046927SAndroid Build Coastguard Worker "expected: %s, found %s",
1426*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type->fields.array),
1427*61046927SAndroid Build Coastguard Worker glsl_get_type_name(ir->type));
1428*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
1429*61046927SAndroid Build Coastguard Worker } else {
1430*61046927SAndroid Build Coastguard Worker element_type = ir->type;
1431*61046927SAndroid Build Coastguard Worker }
1432*61046927SAndroid Build Coastguard Worker }
1433*61046927SAndroid Build Coastguard Worker
1434*61046927SAndroid Build Coastguard Worker if (glsl_type_is_unsized_array(constructor_type->fields.array)) {
1435*61046927SAndroid Build Coastguard Worker constructor_type =
1436*61046927SAndroid Build Coastguard Worker glsl_array_type(element_type, parameter_count, 0);
1437*61046927SAndroid Build Coastguard Worker assert(constructor_type != NULL);
1438*61046927SAndroid Build Coastguard Worker assert(constructor_type->length == parameter_count);
1439*61046927SAndroid Build Coastguard Worker }
1440*61046927SAndroid Build Coastguard Worker
1441*61046927SAndroid Build Coastguard Worker if (all_parameters_are_constant)
1442*61046927SAndroid Build Coastguard Worker return new(ctx) ir_constant(constructor_type, &actual_parameters);
1443*61046927SAndroid Build Coastguard Worker
1444*61046927SAndroid Build Coastguard Worker ir_variable *var = new(ctx) ir_variable(constructor_type, "array_ctor",
1445*61046927SAndroid Build Coastguard Worker ir_var_temporary);
1446*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
1447*61046927SAndroid Build Coastguard Worker
1448*61046927SAndroid Build Coastguard Worker int i = 0;
1449*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_rvalue, rhs, &actual_parameters) {
1450*61046927SAndroid Build Coastguard Worker ir_rvalue *lhs = new(ctx) ir_dereference_array(var,
1451*61046927SAndroid Build Coastguard Worker new(ctx) ir_constant(i));
1452*61046927SAndroid Build Coastguard Worker
1453*61046927SAndroid Build Coastguard Worker ir_instruction *assignment = new(ctx) ir_assignment(lhs, rhs);
1454*61046927SAndroid Build Coastguard Worker instructions->push_tail(assignment);
1455*61046927SAndroid Build Coastguard Worker
1456*61046927SAndroid Build Coastguard Worker i++;
1457*61046927SAndroid Build Coastguard Worker }
1458*61046927SAndroid Build Coastguard Worker
1459*61046927SAndroid Build Coastguard Worker return new(ctx) ir_dereference_variable(var);
1460*61046927SAndroid Build Coastguard Worker }
1461*61046927SAndroid Build Coastguard Worker
1462*61046927SAndroid Build Coastguard Worker
1463*61046927SAndroid Build Coastguard Worker /**
1464*61046927SAndroid Build Coastguard Worker * Determine if a list consists of a single scalar r-value
1465*61046927SAndroid Build Coastguard Worker */
1466*61046927SAndroid Build Coastguard Worker static bool
single_scalar_parameter(exec_list * parameters)1467*61046927SAndroid Build Coastguard Worker single_scalar_parameter(exec_list *parameters)
1468*61046927SAndroid Build Coastguard Worker {
1469*61046927SAndroid Build Coastguard Worker const ir_rvalue *const p = (ir_rvalue *) parameters->get_head_raw();
1470*61046927SAndroid Build Coastguard Worker assert(((ir_rvalue *)p)->as_rvalue() != NULL);
1471*61046927SAndroid Build Coastguard Worker
1472*61046927SAndroid Build Coastguard Worker return (glsl_type_is_scalar(p->type) && p->next->is_tail_sentinel());
1473*61046927SAndroid Build Coastguard Worker }
1474*61046927SAndroid Build Coastguard Worker
1475*61046927SAndroid Build Coastguard Worker
1476*61046927SAndroid Build Coastguard Worker /**
1477*61046927SAndroid Build Coastguard Worker * Generate inline code for a vector constructor
1478*61046927SAndroid Build Coastguard Worker *
1479*61046927SAndroid Build Coastguard Worker * The generated constructor code will consist of a temporary variable
1480*61046927SAndroid Build Coastguard Worker * declaration of the same type as the constructor. A sequence of assignments
1481*61046927SAndroid Build Coastguard Worker * from constructor parameters to the temporary will follow.
1482*61046927SAndroid Build Coastguard Worker *
1483*61046927SAndroid Build Coastguard Worker * \return
1484*61046927SAndroid Build Coastguard Worker * An \c ir_dereference_variable of the temprorary generated in the constructor
1485*61046927SAndroid Build Coastguard Worker * body.
1486*61046927SAndroid Build Coastguard Worker */
1487*61046927SAndroid Build Coastguard Worker static ir_rvalue *
emit_inline_vector_constructor(const glsl_type * type,exec_list * instructions,exec_list * parameters,void * ctx)1488*61046927SAndroid Build Coastguard Worker emit_inline_vector_constructor(const glsl_type *type,
1489*61046927SAndroid Build Coastguard Worker exec_list *instructions,
1490*61046927SAndroid Build Coastguard Worker exec_list *parameters,
1491*61046927SAndroid Build Coastguard Worker void *ctx)
1492*61046927SAndroid Build Coastguard Worker {
1493*61046927SAndroid Build Coastguard Worker assert(!parameters->is_empty());
1494*61046927SAndroid Build Coastguard Worker
1495*61046927SAndroid Build Coastguard Worker ir_variable *var = new(ctx) ir_variable(type, "vec_ctor", ir_var_temporary);
1496*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
1497*61046927SAndroid Build Coastguard Worker
1498*61046927SAndroid Build Coastguard Worker /* There are three kinds of vector constructors.
1499*61046927SAndroid Build Coastguard Worker *
1500*61046927SAndroid Build Coastguard Worker * - Construct a vector from a single scalar by replicating that scalar to
1501*61046927SAndroid Build Coastguard Worker * all components of the vector.
1502*61046927SAndroid Build Coastguard Worker *
1503*61046927SAndroid Build Coastguard Worker * - Construct a vector from at least a matrix. This case should already
1504*61046927SAndroid Build Coastguard Worker * have been taken care of in ast_function_expression::hir by breaking
1505*61046927SAndroid Build Coastguard Worker * down the matrix into a series of column vectors.
1506*61046927SAndroid Build Coastguard Worker *
1507*61046927SAndroid Build Coastguard Worker * - Construct a vector from an arbirary combination of vectors and
1508*61046927SAndroid Build Coastguard Worker * scalars. The components of the constructor parameters are assigned
1509*61046927SAndroid Build Coastguard Worker * to the vector in order until the vector is full.
1510*61046927SAndroid Build Coastguard Worker */
1511*61046927SAndroid Build Coastguard Worker const unsigned lhs_components = glsl_get_components(type);
1512*61046927SAndroid Build Coastguard Worker if (single_scalar_parameter(parameters)) {
1513*61046927SAndroid Build Coastguard Worker ir_rvalue *first_param = (ir_rvalue *)parameters->get_head_raw();
1514*61046927SAndroid Build Coastguard Worker return new(ctx) ir_swizzle(first_param, 0, 0, 0, 0, lhs_components);
1515*61046927SAndroid Build Coastguard Worker } else {
1516*61046927SAndroid Build Coastguard Worker unsigned base_component = 0;
1517*61046927SAndroid Build Coastguard Worker unsigned base_lhs_component = 0;
1518*61046927SAndroid Build Coastguard Worker ir_constant_data data;
1519*61046927SAndroid Build Coastguard Worker unsigned constant_mask = 0, constant_components = 0;
1520*61046927SAndroid Build Coastguard Worker
1521*61046927SAndroid Build Coastguard Worker memset(&data, 0, sizeof(data));
1522*61046927SAndroid Build Coastguard Worker
1523*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_rvalue, param, parameters) {
1524*61046927SAndroid Build Coastguard Worker unsigned rhs_components = glsl_get_components(param->type);
1525*61046927SAndroid Build Coastguard Worker
1526*61046927SAndroid Build Coastguard Worker /* Do not try to assign more components to the vector than it has! */
1527*61046927SAndroid Build Coastguard Worker if ((rhs_components + base_lhs_component) > lhs_components) {
1528*61046927SAndroid Build Coastguard Worker rhs_components = lhs_components - base_lhs_component;
1529*61046927SAndroid Build Coastguard Worker }
1530*61046927SAndroid Build Coastguard Worker
1531*61046927SAndroid Build Coastguard Worker const ir_constant *const c = param->as_constant();
1532*61046927SAndroid Build Coastguard Worker if (c != NULL) {
1533*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < rhs_components; i++) {
1534*61046927SAndroid Build Coastguard Worker switch (c->type->base_type) {
1535*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT:
1536*61046927SAndroid Build Coastguard Worker data.u[i + base_component] = c->get_uint_component(i);
1537*61046927SAndroid Build Coastguard Worker break;
1538*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT:
1539*61046927SAndroid Build Coastguard Worker data.i[i + base_component] = c->get_int_component(i);
1540*61046927SAndroid Build Coastguard Worker break;
1541*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_FLOAT:
1542*61046927SAndroid Build Coastguard Worker data.f[i + base_component] = c->get_float_component(i);
1543*61046927SAndroid Build Coastguard Worker break;
1544*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_DOUBLE:
1545*61046927SAndroid Build Coastguard Worker data.d[i + base_component] = c->get_double_component(i);
1546*61046927SAndroid Build Coastguard Worker break;
1547*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_BOOL:
1548*61046927SAndroid Build Coastguard Worker data.b[i + base_component] = c->get_bool_component(i);
1549*61046927SAndroid Build Coastguard Worker break;
1550*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_UINT64:
1551*61046927SAndroid Build Coastguard Worker data.u64[i + base_component] = c->get_uint64_component(i);
1552*61046927SAndroid Build Coastguard Worker break;
1553*61046927SAndroid Build Coastguard Worker case GLSL_TYPE_INT64:
1554*61046927SAndroid Build Coastguard Worker data.i64[i + base_component] = c->get_int64_component(i);
1555*61046927SAndroid Build Coastguard Worker break;
1556*61046927SAndroid Build Coastguard Worker default:
1557*61046927SAndroid Build Coastguard Worker assert(!"Should not get here.");
1558*61046927SAndroid Build Coastguard Worker break;
1559*61046927SAndroid Build Coastguard Worker }
1560*61046927SAndroid Build Coastguard Worker }
1561*61046927SAndroid Build Coastguard Worker
1562*61046927SAndroid Build Coastguard Worker /* Mask of fields to be written in the assignment. */
1563*61046927SAndroid Build Coastguard Worker constant_mask |= ((1U << rhs_components) - 1) << base_lhs_component;
1564*61046927SAndroid Build Coastguard Worker constant_components += rhs_components;
1565*61046927SAndroid Build Coastguard Worker
1566*61046927SAndroid Build Coastguard Worker base_component += rhs_components;
1567*61046927SAndroid Build Coastguard Worker }
1568*61046927SAndroid Build Coastguard Worker /* Advance the component index by the number of components
1569*61046927SAndroid Build Coastguard Worker * that were just assigned.
1570*61046927SAndroid Build Coastguard Worker */
1571*61046927SAndroid Build Coastguard Worker base_lhs_component += rhs_components;
1572*61046927SAndroid Build Coastguard Worker }
1573*61046927SAndroid Build Coastguard Worker
1574*61046927SAndroid Build Coastguard Worker if (constant_mask != 0) {
1575*61046927SAndroid Build Coastguard Worker ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
1576*61046927SAndroid Build Coastguard Worker const glsl_type *rhs_type =
1577*61046927SAndroid Build Coastguard Worker glsl_simple_type(var->type->base_type, constant_components, 1);
1578*61046927SAndroid Build Coastguard Worker ir_rvalue *rhs = new(ctx) ir_constant(rhs_type, &data);
1579*61046927SAndroid Build Coastguard Worker
1580*61046927SAndroid Build Coastguard Worker ir_instruction *inst =
1581*61046927SAndroid Build Coastguard Worker new(ctx) ir_assignment(lhs, rhs, constant_mask);
1582*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1583*61046927SAndroid Build Coastguard Worker }
1584*61046927SAndroid Build Coastguard Worker
1585*61046927SAndroid Build Coastguard Worker base_component = 0;
1586*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_rvalue, param, parameters) {
1587*61046927SAndroid Build Coastguard Worker unsigned rhs_components = glsl_get_components(param->type);
1588*61046927SAndroid Build Coastguard Worker
1589*61046927SAndroid Build Coastguard Worker /* Do not try to assign more components to the vector than it has! */
1590*61046927SAndroid Build Coastguard Worker if ((rhs_components + base_component) > lhs_components) {
1591*61046927SAndroid Build Coastguard Worker rhs_components = lhs_components - base_component;
1592*61046927SAndroid Build Coastguard Worker }
1593*61046927SAndroid Build Coastguard Worker
1594*61046927SAndroid Build Coastguard Worker /* If we do not have any components left to copy, break out of the
1595*61046927SAndroid Build Coastguard Worker * loop. This can happen when initializing a vec4 with a mat3 as the
1596*61046927SAndroid Build Coastguard Worker * mat3 would have been broken into a series of column vectors.
1597*61046927SAndroid Build Coastguard Worker */
1598*61046927SAndroid Build Coastguard Worker if (rhs_components == 0) {
1599*61046927SAndroid Build Coastguard Worker break;
1600*61046927SAndroid Build Coastguard Worker }
1601*61046927SAndroid Build Coastguard Worker
1602*61046927SAndroid Build Coastguard Worker const ir_constant *const c = param->as_constant();
1603*61046927SAndroid Build Coastguard Worker if (c == NULL) {
1604*61046927SAndroid Build Coastguard Worker /* Mask of fields to be written in the assignment. */
1605*61046927SAndroid Build Coastguard Worker const unsigned write_mask = ((1U << rhs_components) - 1)
1606*61046927SAndroid Build Coastguard Worker << base_component;
1607*61046927SAndroid Build Coastguard Worker
1608*61046927SAndroid Build Coastguard Worker ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
1609*61046927SAndroid Build Coastguard Worker
1610*61046927SAndroid Build Coastguard Worker /* Generate a swizzle so that LHS and RHS sizes match. */
1611*61046927SAndroid Build Coastguard Worker ir_rvalue *rhs =
1612*61046927SAndroid Build Coastguard Worker new(ctx) ir_swizzle(param, 0, 1, 2, 3, rhs_components);
1613*61046927SAndroid Build Coastguard Worker
1614*61046927SAndroid Build Coastguard Worker ir_instruction *inst =
1615*61046927SAndroid Build Coastguard Worker new(ctx) ir_assignment(lhs, rhs, write_mask);
1616*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1617*61046927SAndroid Build Coastguard Worker }
1618*61046927SAndroid Build Coastguard Worker
1619*61046927SAndroid Build Coastguard Worker /* Advance the component index by the number of components that were
1620*61046927SAndroid Build Coastguard Worker * just assigned.
1621*61046927SAndroid Build Coastguard Worker */
1622*61046927SAndroid Build Coastguard Worker base_component += rhs_components;
1623*61046927SAndroid Build Coastguard Worker }
1624*61046927SAndroid Build Coastguard Worker }
1625*61046927SAndroid Build Coastguard Worker return new(ctx) ir_dereference_variable(var);
1626*61046927SAndroid Build Coastguard Worker }
1627*61046927SAndroid Build Coastguard Worker
1628*61046927SAndroid Build Coastguard Worker
1629*61046927SAndroid Build Coastguard Worker /**
1630*61046927SAndroid Build Coastguard Worker * Generate assignment of a portion of a vector to a portion of a matrix column
1631*61046927SAndroid Build Coastguard Worker *
1632*61046927SAndroid Build Coastguard Worker * \param src_base First component of the source to be used in assignment
1633*61046927SAndroid Build Coastguard Worker * \param column Column of destination to be assiged
1634*61046927SAndroid Build Coastguard Worker * \param row_base First component of the destination column to be assigned
1635*61046927SAndroid Build Coastguard Worker * \param count Number of components to be assigned
1636*61046927SAndroid Build Coastguard Worker *
1637*61046927SAndroid Build Coastguard Worker * \note
1638*61046927SAndroid Build Coastguard Worker * \c src_base + \c count must be less than or equal to the number of
1639*61046927SAndroid Build Coastguard Worker * components in the source vector.
1640*61046927SAndroid Build Coastguard Worker */
1641*61046927SAndroid Build Coastguard Worker static ir_instruction *
assign_to_matrix_column(ir_variable * var,unsigned column,unsigned row_base,ir_rvalue * src,unsigned src_base,unsigned count,void * mem_ctx)1642*61046927SAndroid Build Coastguard Worker assign_to_matrix_column(ir_variable *var, unsigned column, unsigned row_base,
1643*61046927SAndroid Build Coastguard Worker ir_rvalue *src, unsigned src_base, unsigned count,
1644*61046927SAndroid Build Coastguard Worker void *mem_ctx)
1645*61046927SAndroid Build Coastguard Worker {
1646*61046927SAndroid Build Coastguard Worker ir_constant *col_idx = new(mem_ctx) ir_constant(column);
1647*61046927SAndroid Build Coastguard Worker ir_dereference *column_ref = new(mem_ctx) ir_dereference_array(var,
1648*61046927SAndroid Build Coastguard Worker col_idx);
1649*61046927SAndroid Build Coastguard Worker
1650*61046927SAndroid Build Coastguard Worker assert(glsl_get_components(column_ref->type) >= (row_base + count));
1651*61046927SAndroid Build Coastguard Worker assert(glsl_get_components(src->type) >= (src_base + count));
1652*61046927SAndroid Build Coastguard Worker
1653*61046927SAndroid Build Coastguard Worker /* Generate a swizzle that extracts the number of components from the source
1654*61046927SAndroid Build Coastguard Worker * that are to be assigned to the column of the matrix.
1655*61046927SAndroid Build Coastguard Worker */
1656*61046927SAndroid Build Coastguard Worker if (count < src->type->vector_elements) {
1657*61046927SAndroid Build Coastguard Worker src = new(mem_ctx) ir_swizzle(src,
1658*61046927SAndroid Build Coastguard Worker src_base + 0, src_base + 1,
1659*61046927SAndroid Build Coastguard Worker src_base + 2, src_base + 3,
1660*61046927SAndroid Build Coastguard Worker count);
1661*61046927SAndroid Build Coastguard Worker }
1662*61046927SAndroid Build Coastguard Worker
1663*61046927SAndroid Build Coastguard Worker /* Mask of fields to be written in the assignment. */
1664*61046927SAndroid Build Coastguard Worker const unsigned write_mask = ((1U << count) - 1) << row_base;
1665*61046927SAndroid Build Coastguard Worker
1666*61046927SAndroid Build Coastguard Worker return new(mem_ctx) ir_assignment(column_ref, src, write_mask);
1667*61046927SAndroid Build Coastguard Worker }
1668*61046927SAndroid Build Coastguard Worker
1669*61046927SAndroid Build Coastguard Worker
1670*61046927SAndroid Build Coastguard Worker /**
1671*61046927SAndroid Build Coastguard Worker * Generate inline code for a matrix constructor
1672*61046927SAndroid Build Coastguard Worker *
1673*61046927SAndroid Build Coastguard Worker * The generated constructor code will consist of a temporary variable
1674*61046927SAndroid Build Coastguard Worker * declaration of the same type as the constructor. A sequence of assignments
1675*61046927SAndroid Build Coastguard Worker * from constructor parameters to the temporary will follow.
1676*61046927SAndroid Build Coastguard Worker *
1677*61046927SAndroid Build Coastguard Worker * \return
1678*61046927SAndroid Build Coastguard Worker * An \c ir_dereference_variable of the temprorary generated in the constructor
1679*61046927SAndroid Build Coastguard Worker * body.
1680*61046927SAndroid Build Coastguard Worker */
1681*61046927SAndroid Build Coastguard Worker static ir_rvalue *
emit_inline_matrix_constructor(const glsl_type * type,exec_list * instructions,exec_list * parameters,void * ctx)1682*61046927SAndroid Build Coastguard Worker emit_inline_matrix_constructor(const glsl_type *type,
1683*61046927SAndroid Build Coastguard Worker exec_list *instructions,
1684*61046927SAndroid Build Coastguard Worker exec_list *parameters,
1685*61046927SAndroid Build Coastguard Worker void *ctx)
1686*61046927SAndroid Build Coastguard Worker {
1687*61046927SAndroid Build Coastguard Worker assert(!parameters->is_empty());
1688*61046927SAndroid Build Coastguard Worker
1689*61046927SAndroid Build Coastguard Worker ir_variable *var = new(ctx) ir_variable(type, "mat_ctor", ir_var_temporary);
1690*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
1691*61046927SAndroid Build Coastguard Worker
1692*61046927SAndroid Build Coastguard Worker /* There are three kinds of matrix constructors.
1693*61046927SAndroid Build Coastguard Worker *
1694*61046927SAndroid Build Coastguard Worker * - Construct a matrix from a single scalar by replicating that scalar to
1695*61046927SAndroid Build Coastguard Worker * along the diagonal of the matrix and setting all other components to
1696*61046927SAndroid Build Coastguard Worker * zero.
1697*61046927SAndroid Build Coastguard Worker *
1698*61046927SAndroid Build Coastguard Worker * - Construct a matrix from an arbirary combination of vectors and
1699*61046927SAndroid Build Coastguard Worker * scalars. The components of the constructor parameters are assigned
1700*61046927SAndroid Build Coastguard Worker * to the matrix in column-major order until the matrix is full.
1701*61046927SAndroid Build Coastguard Worker *
1702*61046927SAndroid Build Coastguard Worker * - Construct a matrix from a single matrix. The source matrix is copied
1703*61046927SAndroid Build Coastguard Worker * to the upper left portion of the constructed matrix, and the remaining
1704*61046927SAndroid Build Coastguard Worker * elements take values from the identity matrix.
1705*61046927SAndroid Build Coastguard Worker */
1706*61046927SAndroid Build Coastguard Worker ir_rvalue *const first_param = (ir_rvalue *) parameters->get_head_raw();
1707*61046927SAndroid Build Coastguard Worker if (single_scalar_parameter(parameters)) {
1708*61046927SAndroid Build Coastguard Worker /* Assign the scalar to the X component of a vec4, and fill the remaining
1709*61046927SAndroid Build Coastguard Worker * components with zero.
1710*61046927SAndroid Build Coastguard Worker */
1711*61046927SAndroid Build Coastguard Worker glsl_base_type param_base_type = first_param->type->base_type;
1712*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_float_16_32_64(first_param->type));
1713*61046927SAndroid Build Coastguard Worker ir_variable *rhs_var =
1714*61046927SAndroid Build Coastguard Worker new(ctx) ir_variable(glsl_simple_type(param_base_type, 4, 1),
1715*61046927SAndroid Build Coastguard Worker "mat_ctor_vec",
1716*61046927SAndroid Build Coastguard Worker ir_var_temporary);
1717*61046927SAndroid Build Coastguard Worker instructions->push_tail(rhs_var);
1718*61046927SAndroid Build Coastguard Worker
1719*61046927SAndroid Build Coastguard Worker ir_constant_data zero;
1720*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < 4; i++)
1721*61046927SAndroid Build Coastguard Worker if (glsl_type_is_float(first_param->type))
1722*61046927SAndroid Build Coastguard Worker zero.f[i] = 0.0;
1723*61046927SAndroid Build Coastguard Worker else
1724*61046927SAndroid Build Coastguard Worker zero.d[i] = 0.0;
1725*61046927SAndroid Build Coastguard Worker
1726*61046927SAndroid Build Coastguard Worker ir_instruction *inst =
1727*61046927SAndroid Build Coastguard Worker new(ctx) ir_assignment(new(ctx) ir_dereference_variable(rhs_var),
1728*61046927SAndroid Build Coastguard Worker new(ctx) ir_constant(rhs_var->type, &zero));
1729*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1730*61046927SAndroid Build Coastguard Worker
1731*61046927SAndroid Build Coastguard Worker ir_dereference *const rhs_ref =
1732*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_variable(rhs_var);
1733*61046927SAndroid Build Coastguard Worker
1734*61046927SAndroid Build Coastguard Worker inst = new(ctx) ir_assignment(rhs_ref, first_param, 0x01);
1735*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1736*61046927SAndroid Build Coastguard Worker
1737*61046927SAndroid Build Coastguard Worker /* Assign the temporary vector to each column of the destination matrix
1738*61046927SAndroid Build Coastguard Worker * with a swizzle that puts the X component on the diagonal of the
1739*61046927SAndroid Build Coastguard Worker * matrix. In some cases this may mean that the X component does not
1740*61046927SAndroid Build Coastguard Worker * get assigned into the column at all (i.e., when the matrix has more
1741*61046927SAndroid Build Coastguard Worker * columns than rows).
1742*61046927SAndroid Build Coastguard Worker */
1743*61046927SAndroid Build Coastguard Worker static const unsigned rhs_swiz[4][4] = {
1744*61046927SAndroid Build Coastguard Worker { 0, 1, 1, 1 },
1745*61046927SAndroid Build Coastguard Worker { 1, 0, 1, 1 },
1746*61046927SAndroid Build Coastguard Worker { 1, 1, 0, 1 },
1747*61046927SAndroid Build Coastguard Worker { 1, 1, 1, 0 }
1748*61046927SAndroid Build Coastguard Worker };
1749*61046927SAndroid Build Coastguard Worker
1750*61046927SAndroid Build Coastguard Worker const unsigned cols_to_init = MIN2(type->matrix_columns,
1751*61046927SAndroid Build Coastguard Worker type->vector_elements);
1752*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < cols_to_init; i++) {
1753*61046927SAndroid Build Coastguard Worker ir_constant *const col_idx = new(ctx) ir_constant(i);
1754*61046927SAndroid Build Coastguard Worker ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var,
1755*61046927SAndroid Build Coastguard Worker col_idx);
1756*61046927SAndroid Build Coastguard Worker
1757*61046927SAndroid Build Coastguard Worker ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
1758*61046927SAndroid Build Coastguard Worker ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, rhs_swiz[i],
1759*61046927SAndroid Build Coastguard Worker type->vector_elements);
1760*61046927SAndroid Build Coastguard Worker
1761*61046927SAndroid Build Coastguard Worker inst = new(ctx) ir_assignment(col_ref, rhs);
1762*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1763*61046927SAndroid Build Coastguard Worker }
1764*61046927SAndroid Build Coastguard Worker
1765*61046927SAndroid Build Coastguard Worker for (unsigned i = cols_to_init; i < type->matrix_columns; i++) {
1766*61046927SAndroid Build Coastguard Worker ir_constant *const col_idx = new(ctx) ir_constant(i);
1767*61046927SAndroid Build Coastguard Worker ir_rvalue *const col_ref = new(ctx) ir_dereference_array(var,
1768*61046927SAndroid Build Coastguard Worker col_idx);
1769*61046927SAndroid Build Coastguard Worker
1770*61046927SAndroid Build Coastguard Worker ir_rvalue *const rhs_ref = new(ctx) ir_dereference_variable(rhs_var);
1771*61046927SAndroid Build Coastguard Worker ir_rvalue *const rhs = new(ctx) ir_swizzle(rhs_ref, 1, 1, 1, 1,
1772*61046927SAndroid Build Coastguard Worker type->vector_elements);
1773*61046927SAndroid Build Coastguard Worker
1774*61046927SAndroid Build Coastguard Worker inst = new(ctx) ir_assignment(col_ref, rhs);
1775*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1776*61046927SAndroid Build Coastguard Worker }
1777*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_matrix(first_param->type)) {
1778*61046927SAndroid Build Coastguard Worker /* From page 50 (56 of the PDF) of the GLSL 1.50 spec:
1779*61046927SAndroid Build Coastguard Worker *
1780*61046927SAndroid Build Coastguard Worker * "If a matrix is constructed from a matrix, then each component
1781*61046927SAndroid Build Coastguard Worker * (column i, row j) in the result that has a corresponding
1782*61046927SAndroid Build Coastguard Worker * component (column i, row j) in the argument will be initialized
1783*61046927SAndroid Build Coastguard Worker * from there. All other components will be initialized to the
1784*61046927SAndroid Build Coastguard Worker * identity matrix. If a matrix argument is given to a matrix
1785*61046927SAndroid Build Coastguard Worker * constructor, it is an error to have any other arguments."
1786*61046927SAndroid Build Coastguard Worker */
1787*61046927SAndroid Build Coastguard Worker assert(first_param->next->is_tail_sentinel());
1788*61046927SAndroid Build Coastguard Worker ir_rvalue *const src_matrix = first_param;
1789*61046927SAndroid Build Coastguard Worker
1790*61046927SAndroid Build Coastguard Worker /* If the source matrix is smaller, pre-initialize the relavent parts of
1791*61046927SAndroid Build Coastguard Worker * the destination matrix to the identity matrix.
1792*61046927SAndroid Build Coastguard Worker */
1793*61046927SAndroid Build Coastguard Worker if ((src_matrix->type->matrix_columns < var->type->matrix_columns) ||
1794*61046927SAndroid Build Coastguard Worker (src_matrix->type->vector_elements < var->type->vector_elements)) {
1795*61046927SAndroid Build Coastguard Worker
1796*61046927SAndroid Build Coastguard Worker /* If the source matrix has fewer rows, every column of the
1797*61046927SAndroid Build Coastguard Worker * destination must be initialized. Otherwise only the columns in
1798*61046927SAndroid Build Coastguard Worker * the destination that do not exist in the source must be
1799*61046927SAndroid Build Coastguard Worker * initialized.
1800*61046927SAndroid Build Coastguard Worker */
1801*61046927SAndroid Build Coastguard Worker unsigned col =
1802*61046927SAndroid Build Coastguard Worker (src_matrix->type->vector_elements < var->type->vector_elements)
1803*61046927SAndroid Build Coastguard Worker ? 0 : src_matrix->type->matrix_columns;
1804*61046927SAndroid Build Coastguard Worker
1805*61046927SAndroid Build Coastguard Worker const glsl_type *const col_type = glsl_get_column_type(var->type);
1806*61046927SAndroid Build Coastguard Worker for (/* empty */; col < var->type->matrix_columns; col++) {
1807*61046927SAndroid Build Coastguard Worker ir_constant_data ident;
1808*61046927SAndroid Build Coastguard Worker
1809*61046927SAndroid Build Coastguard Worker if (!glsl_type_is_double(col_type)) {
1810*61046927SAndroid Build Coastguard Worker ident.f[0] = 0.0f;
1811*61046927SAndroid Build Coastguard Worker ident.f[1] = 0.0f;
1812*61046927SAndroid Build Coastguard Worker ident.f[2] = 0.0f;
1813*61046927SAndroid Build Coastguard Worker ident.f[3] = 0.0f;
1814*61046927SAndroid Build Coastguard Worker ident.f[col] = 1.0f;
1815*61046927SAndroid Build Coastguard Worker } else {
1816*61046927SAndroid Build Coastguard Worker ident.d[0] = 0.0;
1817*61046927SAndroid Build Coastguard Worker ident.d[1] = 0.0;
1818*61046927SAndroid Build Coastguard Worker ident.d[2] = 0.0;
1819*61046927SAndroid Build Coastguard Worker ident.d[3] = 0.0;
1820*61046927SAndroid Build Coastguard Worker ident.d[col] = 1.0;
1821*61046927SAndroid Build Coastguard Worker }
1822*61046927SAndroid Build Coastguard Worker
1823*61046927SAndroid Build Coastguard Worker ir_rvalue *const rhs = new(ctx) ir_constant(col_type, &ident);
1824*61046927SAndroid Build Coastguard Worker
1825*61046927SAndroid Build Coastguard Worker ir_rvalue *const lhs =
1826*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_array(var, new(ctx) ir_constant(col));
1827*61046927SAndroid Build Coastguard Worker
1828*61046927SAndroid Build Coastguard Worker ir_instruction *inst = new(ctx) ir_assignment(lhs, rhs);
1829*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1830*61046927SAndroid Build Coastguard Worker }
1831*61046927SAndroid Build Coastguard Worker }
1832*61046927SAndroid Build Coastguard Worker
1833*61046927SAndroid Build Coastguard Worker /* Assign columns from the source matrix to the destination matrix.
1834*61046927SAndroid Build Coastguard Worker *
1835*61046927SAndroid Build Coastguard Worker * Since the parameter will be used in the RHS of multiple assignments,
1836*61046927SAndroid Build Coastguard Worker * generate a temporary and copy the paramter there.
1837*61046927SAndroid Build Coastguard Worker */
1838*61046927SAndroid Build Coastguard Worker ir_variable *const rhs_var =
1839*61046927SAndroid Build Coastguard Worker new(ctx) ir_variable(first_param->type, "mat_ctor_mat",
1840*61046927SAndroid Build Coastguard Worker ir_var_temporary);
1841*61046927SAndroid Build Coastguard Worker instructions->push_tail(rhs_var);
1842*61046927SAndroid Build Coastguard Worker
1843*61046927SAndroid Build Coastguard Worker ir_dereference *const rhs_var_ref =
1844*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_variable(rhs_var);
1845*61046927SAndroid Build Coastguard Worker ir_instruction *const inst =
1846*61046927SAndroid Build Coastguard Worker new(ctx) ir_assignment(rhs_var_ref, first_param);
1847*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1848*61046927SAndroid Build Coastguard Worker
1849*61046927SAndroid Build Coastguard Worker const unsigned last_row = MIN2(src_matrix->type->vector_elements,
1850*61046927SAndroid Build Coastguard Worker var->type->vector_elements);
1851*61046927SAndroid Build Coastguard Worker const unsigned last_col = MIN2(src_matrix->type->matrix_columns,
1852*61046927SAndroid Build Coastguard Worker var->type->matrix_columns);
1853*61046927SAndroid Build Coastguard Worker
1854*61046927SAndroid Build Coastguard Worker unsigned swiz[4] = { 0, 0, 0, 0 };
1855*61046927SAndroid Build Coastguard Worker for (unsigned i = 1; i < last_row; i++)
1856*61046927SAndroid Build Coastguard Worker swiz[i] = i;
1857*61046927SAndroid Build Coastguard Worker
1858*61046927SAndroid Build Coastguard Worker const unsigned write_mask = (1U << last_row) - 1;
1859*61046927SAndroid Build Coastguard Worker
1860*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < last_col; i++) {
1861*61046927SAndroid Build Coastguard Worker ir_dereference *const lhs =
1862*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_array(var, new(ctx) ir_constant(i));
1863*61046927SAndroid Build Coastguard Worker ir_rvalue *const rhs_col =
1864*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_array(rhs_var, new(ctx) ir_constant(i));
1865*61046927SAndroid Build Coastguard Worker
1866*61046927SAndroid Build Coastguard Worker /* If one matrix has columns that are smaller than the columns of the
1867*61046927SAndroid Build Coastguard Worker * other matrix, wrap the column access of the larger with a swizzle
1868*61046927SAndroid Build Coastguard Worker * so that the LHS and RHS of the assignment have the same size (and
1869*61046927SAndroid Build Coastguard Worker * therefore have the same type).
1870*61046927SAndroid Build Coastguard Worker *
1871*61046927SAndroid Build Coastguard Worker * It would be perfectly valid to unconditionally generate the
1872*61046927SAndroid Build Coastguard Worker * swizzles, this this will typically result in a more compact IR
1873*61046927SAndroid Build Coastguard Worker * tree.
1874*61046927SAndroid Build Coastguard Worker */
1875*61046927SAndroid Build Coastguard Worker ir_rvalue *rhs;
1876*61046927SAndroid Build Coastguard Worker if (lhs->type->vector_elements != rhs_col->type->vector_elements) {
1877*61046927SAndroid Build Coastguard Worker rhs = new(ctx) ir_swizzle(rhs_col, swiz, last_row);
1878*61046927SAndroid Build Coastguard Worker } else {
1879*61046927SAndroid Build Coastguard Worker rhs = rhs_col;
1880*61046927SAndroid Build Coastguard Worker }
1881*61046927SAndroid Build Coastguard Worker
1882*61046927SAndroid Build Coastguard Worker ir_instruction *inst =
1883*61046927SAndroid Build Coastguard Worker new(ctx) ir_assignment(lhs, rhs, write_mask);
1884*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1885*61046927SAndroid Build Coastguard Worker }
1886*61046927SAndroid Build Coastguard Worker } else {
1887*61046927SAndroid Build Coastguard Worker const unsigned cols = type->matrix_columns;
1888*61046927SAndroid Build Coastguard Worker const unsigned rows = type->vector_elements;
1889*61046927SAndroid Build Coastguard Worker unsigned remaining_slots = rows * cols;
1890*61046927SAndroid Build Coastguard Worker unsigned col_idx = 0;
1891*61046927SAndroid Build Coastguard Worker unsigned row_idx = 0;
1892*61046927SAndroid Build Coastguard Worker
1893*61046927SAndroid Build Coastguard Worker foreach_in_list(ir_rvalue, rhs, parameters) {
1894*61046927SAndroid Build Coastguard Worker unsigned rhs_components = glsl_get_components(rhs->type);
1895*61046927SAndroid Build Coastguard Worker unsigned rhs_base = 0;
1896*61046927SAndroid Build Coastguard Worker
1897*61046927SAndroid Build Coastguard Worker if (remaining_slots == 0)
1898*61046927SAndroid Build Coastguard Worker break;
1899*61046927SAndroid Build Coastguard Worker
1900*61046927SAndroid Build Coastguard Worker /* Since the parameter might be used in the RHS of two assignments,
1901*61046927SAndroid Build Coastguard Worker * generate a temporary and copy the paramter there.
1902*61046927SAndroid Build Coastguard Worker */
1903*61046927SAndroid Build Coastguard Worker ir_variable *rhs_var =
1904*61046927SAndroid Build Coastguard Worker new(ctx) ir_variable(rhs->type, "mat_ctor_vec", ir_var_temporary);
1905*61046927SAndroid Build Coastguard Worker instructions->push_tail(rhs_var);
1906*61046927SAndroid Build Coastguard Worker
1907*61046927SAndroid Build Coastguard Worker ir_dereference *rhs_var_ref =
1908*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_variable(rhs_var);
1909*61046927SAndroid Build Coastguard Worker ir_instruction *inst = new(ctx) ir_assignment(rhs_var_ref, rhs);
1910*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1911*61046927SAndroid Build Coastguard Worker
1912*61046927SAndroid Build Coastguard Worker do {
1913*61046927SAndroid Build Coastguard Worker /* Assign the current parameter to as many components of the matrix
1914*61046927SAndroid Build Coastguard Worker * as it will fill.
1915*61046927SAndroid Build Coastguard Worker *
1916*61046927SAndroid Build Coastguard Worker * NOTE: A single vector parameter can span two matrix columns. A
1917*61046927SAndroid Build Coastguard Worker * single vec4, for example, can completely fill a mat2.
1918*61046927SAndroid Build Coastguard Worker */
1919*61046927SAndroid Build Coastguard Worker unsigned count = MIN2(rows - row_idx,
1920*61046927SAndroid Build Coastguard Worker rhs_components - rhs_base);
1921*61046927SAndroid Build Coastguard Worker
1922*61046927SAndroid Build Coastguard Worker rhs_var_ref = new(ctx) ir_dereference_variable(rhs_var);
1923*61046927SAndroid Build Coastguard Worker ir_instruction *inst = assign_to_matrix_column(var, col_idx,
1924*61046927SAndroid Build Coastguard Worker row_idx,
1925*61046927SAndroid Build Coastguard Worker rhs_var_ref,
1926*61046927SAndroid Build Coastguard Worker rhs_base,
1927*61046927SAndroid Build Coastguard Worker count, ctx);
1928*61046927SAndroid Build Coastguard Worker instructions->push_tail(inst);
1929*61046927SAndroid Build Coastguard Worker rhs_base += count;
1930*61046927SAndroid Build Coastguard Worker row_idx += count;
1931*61046927SAndroid Build Coastguard Worker remaining_slots -= count;
1932*61046927SAndroid Build Coastguard Worker
1933*61046927SAndroid Build Coastguard Worker /* Sometimes, there is still data left in the parameters and
1934*61046927SAndroid Build Coastguard Worker * components left to be set in the destination but in other
1935*61046927SAndroid Build Coastguard Worker * column.
1936*61046927SAndroid Build Coastguard Worker */
1937*61046927SAndroid Build Coastguard Worker if (row_idx >= rows) {
1938*61046927SAndroid Build Coastguard Worker row_idx = 0;
1939*61046927SAndroid Build Coastguard Worker col_idx++;
1940*61046927SAndroid Build Coastguard Worker }
1941*61046927SAndroid Build Coastguard Worker } while(remaining_slots > 0 && rhs_base < rhs_components);
1942*61046927SAndroid Build Coastguard Worker }
1943*61046927SAndroid Build Coastguard Worker }
1944*61046927SAndroid Build Coastguard Worker
1945*61046927SAndroid Build Coastguard Worker return new(ctx) ir_dereference_variable(var);
1946*61046927SAndroid Build Coastguard Worker }
1947*61046927SAndroid Build Coastguard Worker
1948*61046927SAndroid Build Coastguard Worker
1949*61046927SAndroid Build Coastguard Worker static ir_rvalue *
emit_inline_record_constructor(const glsl_type * type,exec_list * instructions,exec_list * parameters,void * mem_ctx)1950*61046927SAndroid Build Coastguard Worker emit_inline_record_constructor(const glsl_type *type,
1951*61046927SAndroid Build Coastguard Worker exec_list *instructions,
1952*61046927SAndroid Build Coastguard Worker exec_list *parameters,
1953*61046927SAndroid Build Coastguard Worker void *mem_ctx)
1954*61046927SAndroid Build Coastguard Worker {
1955*61046927SAndroid Build Coastguard Worker ir_variable *const var =
1956*61046927SAndroid Build Coastguard Worker new(mem_ctx) ir_variable(type, "record_ctor", ir_var_temporary);
1957*61046927SAndroid Build Coastguard Worker ir_dereference_variable *const d =
1958*61046927SAndroid Build Coastguard Worker new(mem_ctx) ir_dereference_variable(var);
1959*61046927SAndroid Build Coastguard Worker
1960*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
1961*61046927SAndroid Build Coastguard Worker
1962*61046927SAndroid Build Coastguard Worker exec_node *node = parameters->get_head_raw();
1963*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < type->length; i++) {
1964*61046927SAndroid Build Coastguard Worker assert(!node->is_tail_sentinel());
1965*61046927SAndroid Build Coastguard Worker
1966*61046927SAndroid Build Coastguard Worker ir_dereference *const lhs =
1967*61046927SAndroid Build Coastguard Worker new(mem_ctx) ir_dereference_record(d->clone(mem_ctx, NULL),
1968*61046927SAndroid Build Coastguard Worker type->fields.structure[i].name);
1969*61046927SAndroid Build Coastguard Worker
1970*61046927SAndroid Build Coastguard Worker ir_rvalue *const rhs = ((ir_instruction *) node)->as_rvalue();
1971*61046927SAndroid Build Coastguard Worker assert(rhs != NULL);
1972*61046927SAndroid Build Coastguard Worker
1973*61046927SAndroid Build Coastguard Worker ir_instruction *const assign = new(mem_ctx) ir_assignment(lhs, rhs);
1974*61046927SAndroid Build Coastguard Worker
1975*61046927SAndroid Build Coastguard Worker instructions->push_tail(assign);
1976*61046927SAndroid Build Coastguard Worker node = node->next;
1977*61046927SAndroid Build Coastguard Worker }
1978*61046927SAndroid Build Coastguard Worker
1979*61046927SAndroid Build Coastguard Worker return d;
1980*61046927SAndroid Build Coastguard Worker }
1981*61046927SAndroid Build Coastguard Worker
1982*61046927SAndroid Build Coastguard Worker
1983*61046927SAndroid Build Coastguard Worker static ir_rvalue *
process_record_constructor(exec_list * instructions,const glsl_type * constructor_type,YYLTYPE * loc,exec_list * parameters,struct _mesa_glsl_parse_state * state)1984*61046927SAndroid Build Coastguard Worker process_record_constructor(exec_list *instructions,
1985*61046927SAndroid Build Coastguard Worker const glsl_type *constructor_type,
1986*61046927SAndroid Build Coastguard Worker YYLTYPE *loc, exec_list *parameters,
1987*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
1988*61046927SAndroid Build Coastguard Worker {
1989*61046927SAndroid Build Coastguard Worker void *ctx = state;
1990*61046927SAndroid Build Coastguard Worker /* From page 32 (page 38 of the PDF) of the GLSL 1.20 spec:
1991*61046927SAndroid Build Coastguard Worker *
1992*61046927SAndroid Build Coastguard Worker * "The arguments to the constructor will be used to set the structure's
1993*61046927SAndroid Build Coastguard Worker * fields, in order, using one argument per field. Each argument must
1994*61046927SAndroid Build Coastguard Worker * be the same type as the field it sets, or be a type that can be
1995*61046927SAndroid Build Coastguard Worker * converted to the field's type according to Section 4.1.10 “Implicit
1996*61046927SAndroid Build Coastguard Worker * Conversions.”"
1997*61046927SAndroid Build Coastguard Worker *
1998*61046927SAndroid Build Coastguard Worker * From page 35 (page 41 of the PDF) of the GLSL 4.20 spec:
1999*61046927SAndroid Build Coastguard Worker *
2000*61046927SAndroid Build Coastguard Worker * "In all cases, the innermost initializer (i.e., not a list of
2001*61046927SAndroid Build Coastguard Worker * initializers enclosed in curly braces) applied to an object must
2002*61046927SAndroid Build Coastguard Worker * have the same type as the object being initialized or be a type that
2003*61046927SAndroid Build Coastguard Worker * can be converted to the object's type according to section 4.1.10
2004*61046927SAndroid Build Coastguard Worker * "Implicit Conversions". In the latter case, an implicit conversion
2005*61046927SAndroid Build Coastguard Worker * will be done on the initializer before the assignment is done."
2006*61046927SAndroid Build Coastguard Worker */
2007*61046927SAndroid Build Coastguard Worker exec_list actual_parameters;
2008*61046927SAndroid Build Coastguard Worker
2009*61046927SAndroid Build Coastguard Worker const unsigned parameter_count =
2010*61046927SAndroid Build Coastguard Worker process_parameters(instructions, &actual_parameters, parameters,
2011*61046927SAndroid Build Coastguard Worker state);
2012*61046927SAndroid Build Coastguard Worker
2013*61046927SAndroid Build Coastguard Worker if (parameter_count != constructor_type->length) {
2014*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
2015*61046927SAndroid Build Coastguard Worker "%s parameters in constructor for `%s'",
2016*61046927SAndroid Build Coastguard Worker parameter_count > constructor_type->length
2017*61046927SAndroid Build Coastguard Worker ? "too many": "insufficient",
2018*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type));
2019*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2020*61046927SAndroid Build Coastguard Worker }
2021*61046927SAndroid Build Coastguard Worker
2022*61046927SAndroid Build Coastguard Worker bool all_parameters_are_constant = true;
2023*61046927SAndroid Build Coastguard Worker
2024*61046927SAndroid Build Coastguard Worker int i = 0;
2025*61046927SAndroid Build Coastguard Worker /* Type cast each parameter and, if possible, fold constants. */
2026*61046927SAndroid Build Coastguard Worker foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
2027*61046927SAndroid Build Coastguard Worker
2028*61046927SAndroid Build Coastguard Worker const glsl_struct_field *struct_field =
2029*61046927SAndroid Build Coastguard Worker &constructor_type->fields.structure[i];
2030*61046927SAndroid Build Coastguard Worker
2031*61046927SAndroid Build Coastguard Worker /* Apply implicit conversions (not the scalar constructor rules, see the
2032*61046927SAndroid Build Coastguard Worker * spec quote above!) and attempt to convert the parameter to a constant
2033*61046927SAndroid Build Coastguard Worker * valued expression. After doing so, track whether or not all the
2034*61046927SAndroid Build Coastguard Worker * parameters to the constructor are trivially constant valued
2035*61046927SAndroid Build Coastguard Worker * expressions.
2036*61046927SAndroid Build Coastguard Worker */
2037*61046927SAndroid Build Coastguard Worker all_parameters_are_constant &=
2038*61046927SAndroid Build Coastguard Worker implicitly_convert_component(ir, struct_field->type->base_type,
2039*61046927SAndroid Build Coastguard Worker state);
2040*61046927SAndroid Build Coastguard Worker
2041*61046927SAndroid Build Coastguard Worker if (ir->type != struct_field->type) {
2042*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(loc, state,
2043*61046927SAndroid Build Coastguard Worker "parameter type mismatch in constructor for `%s.%s' "
2044*61046927SAndroid Build Coastguard Worker "(%s vs %s)",
2045*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type),
2046*61046927SAndroid Build Coastguard Worker struct_field->name,
2047*61046927SAndroid Build Coastguard Worker glsl_get_type_name(ir->type),
2048*61046927SAndroid Build Coastguard Worker glsl_get_type_name(struct_field->type));
2049*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2050*61046927SAndroid Build Coastguard Worker }
2051*61046927SAndroid Build Coastguard Worker
2052*61046927SAndroid Build Coastguard Worker i++;
2053*61046927SAndroid Build Coastguard Worker }
2054*61046927SAndroid Build Coastguard Worker
2055*61046927SAndroid Build Coastguard Worker if (all_parameters_are_constant) {
2056*61046927SAndroid Build Coastguard Worker return new(ctx) ir_constant(constructor_type, &actual_parameters);
2057*61046927SAndroid Build Coastguard Worker } else {
2058*61046927SAndroid Build Coastguard Worker return emit_inline_record_constructor(constructor_type, instructions,
2059*61046927SAndroid Build Coastguard Worker &actual_parameters, state);
2060*61046927SAndroid Build Coastguard Worker }
2061*61046927SAndroid Build Coastguard Worker }
2062*61046927SAndroid Build Coastguard Worker
2063*61046927SAndroid Build Coastguard Worker ir_rvalue *
handle_method(exec_list * instructions,struct _mesa_glsl_parse_state * state)2064*61046927SAndroid Build Coastguard Worker ast_function_expression::handle_method(exec_list *instructions,
2065*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
2066*61046927SAndroid Build Coastguard Worker {
2067*61046927SAndroid Build Coastguard Worker const ast_expression *field = subexpressions[0];
2068*61046927SAndroid Build Coastguard Worker ir_rvalue *op;
2069*61046927SAndroid Build Coastguard Worker ir_rvalue *result;
2070*61046927SAndroid Build Coastguard Worker void *ctx = state;
2071*61046927SAndroid Build Coastguard Worker /* Handle "method calls" in GLSL 1.20 - namely, array.length() */
2072*61046927SAndroid Build Coastguard Worker YYLTYPE loc = get_location();
2073*61046927SAndroid Build Coastguard Worker state->check_version(120, 300, &loc, "methods not supported");
2074*61046927SAndroid Build Coastguard Worker
2075*61046927SAndroid Build Coastguard Worker const char *method;
2076*61046927SAndroid Build Coastguard Worker method = field->primary_expression.identifier;
2077*61046927SAndroid Build Coastguard Worker
2078*61046927SAndroid Build Coastguard Worker /* This would prevent to raise "uninitialized variable" warnings when
2079*61046927SAndroid Build Coastguard Worker * calling array.length.
2080*61046927SAndroid Build Coastguard Worker */
2081*61046927SAndroid Build Coastguard Worker field->subexpressions[0]->set_is_lhs(true);
2082*61046927SAndroid Build Coastguard Worker op = field->subexpressions[0]->hir(instructions, state);
2083*61046927SAndroid Build Coastguard Worker if (strcmp(method, "length") == 0) {
2084*61046927SAndroid Build Coastguard Worker if (!this->expressions.is_empty()) {
2085*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "length method takes no arguments");
2086*61046927SAndroid Build Coastguard Worker goto fail;
2087*61046927SAndroid Build Coastguard Worker }
2088*61046927SAndroid Build Coastguard Worker
2089*61046927SAndroid Build Coastguard Worker if (glsl_type_is_array(op->type)) {
2090*61046927SAndroid Build Coastguard Worker if (glsl_type_is_unsized_array(op->type)) {
2091*61046927SAndroid Build Coastguard Worker if (!state->has_shader_storage_buffer_objects()) {
2092*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
2093*61046927SAndroid Build Coastguard Worker "length called on unsized array"
2094*61046927SAndroid Build Coastguard Worker " only available with"
2095*61046927SAndroid Build Coastguard Worker " ARB_shader_storage_buffer_object");
2096*61046927SAndroid Build Coastguard Worker goto fail;
2097*61046927SAndroid Build Coastguard Worker } else if (op->variable_referenced()->is_in_shader_storage_block()) {
2098*61046927SAndroid Build Coastguard Worker /* Calculate length of an unsized array in run-time */
2099*61046927SAndroid Build Coastguard Worker result = new(ctx)
2100*61046927SAndroid Build Coastguard Worker ir_expression(ir_unop_ssbo_unsized_array_length, op);
2101*61046927SAndroid Build Coastguard Worker } else {
2102*61046927SAndroid Build Coastguard Worker /* When actual size is known at link-time, this will be
2103*61046927SAndroid Build Coastguard Worker * replaced with a constant expression.
2104*61046927SAndroid Build Coastguard Worker */
2105*61046927SAndroid Build Coastguard Worker result = new (ctx)
2106*61046927SAndroid Build Coastguard Worker ir_expression(ir_unop_implicitly_sized_array_length, op);
2107*61046927SAndroid Build Coastguard Worker }
2108*61046927SAndroid Build Coastguard Worker } else {
2109*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_constant(glsl_array_size(op->type));
2110*61046927SAndroid Build Coastguard Worker }
2111*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_vector(op->type)) {
2112*61046927SAndroid Build Coastguard Worker if (state->has_420pack()) {
2113*61046927SAndroid Build Coastguard Worker /* .length() returns int. */
2114*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_constant((int) op->type->vector_elements);
2115*61046927SAndroid Build Coastguard Worker } else {
2116*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "length method on matrix only"
2117*61046927SAndroid Build Coastguard Worker " available with ARB_shading_language_420pack");
2118*61046927SAndroid Build Coastguard Worker goto fail;
2119*61046927SAndroid Build Coastguard Worker }
2120*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_matrix(op->type)) {
2121*61046927SAndroid Build Coastguard Worker if (state->has_420pack()) {
2122*61046927SAndroid Build Coastguard Worker /* .length() returns int. */
2123*61046927SAndroid Build Coastguard Worker result = new(ctx) ir_constant((int) op->type->matrix_columns);
2124*61046927SAndroid Build Coastguard Worker } else {
2125*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "length method on matrix only"
2126*61046927SAndroid Build Coastguard Worker " available with ARB_shading_language_420pack");
2127*61046927SAndroid Build Coastguard Worker goto fail;
2128*61046927SAndroid Build Coastguard Worker }
2129*61046927SAndroid Build Coastguard Worker } else {
2130*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "length called on scalar.");
2131*61046927SAndroid Build Coastguard Worker goto fail;
2132*61046927SAndroid Build Coastguard Worker }
2133*61046927SAndroid Build Coastguard Worker } else {
2134*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "unknown method: `%s'", method);
2135*61046927SAndroid Build Coastguard Worker goto fail;
2136*61046927SAndroid Build Coastguard Worker }
2137*61046927SAndroid Build Coastguard Worker return result;
2138*61046927SAndroid Build Coastguard Worker fail:
2139*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2140*61046927SAndroid Build Coastguard Worker }
2141*61046927SAndroid Build Coastguard Worker
is_valid_constructor(const glsl_type * type,struct _mesa_glsl_parse_state * state)2142*61046927SAndroid Build Coastguard Worker static inline bool is_valid_constructor(const glsl_type *type,
2143*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
2144*61046927SAndroid Build Coastguard Worker {
2145*61046927SAndroid Build Coastguard Worker return glsl_type_is_numeric(type) || glsl_type_is_boolean(type) ||
2146*61046927SAndroid Build Coastguard Worker (state->has_bindless() && (glsl_type_is_sampler(type) || glsl_type_is_image(type)));
2147*61046927SAndroid Build Coastguard Worker }
2148*61046927SAndroid Build Coastguard Worker
2149*61046927SAndroid Build Coastguard Worker ir_rvalue *
hir(exec_list * instructions,struct _mesa_glsl_parse_state * state)2150*61046927SAndroid Build Coastguard Worker ast_function_expression::hir(exec_list *instructions,
2151*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
2152*61046927SAndroid Build Coastguard Worker {
2153*61046927SAndroid Build Coastguard Worker void *ctx = state;
2154*61046927SAndroid Build Coastguard Worker /* There are three sorts of function calls.
2155*61046927SAndroid Build Coastguard Worker *
2156*61046927SAndroid Build Coastguard Worker * 1. constructors - The first subexpression is an ast_type_specifier.
2157*61046927SAndroid Build Coastguard Worker * 2. methods - Only the .length() method of array types.
2158*61046927SAndroid Build Coastguard Worker * 3. functions - Calls to regular old functions.
2159*61046927SAndroid Build Coastguard Worker *
2160*61046927SAndroid Build Coastguard Worker */
2161*61046927SAndroid Build Coastguard Worker if (is_constructor()) {
2162*61046927SAndroid Build Coastguard Worker const ast_type_specifier *type =
2163*61046927SAndroid Build Coastguard Worker (ast_type_specifier *) subexpressions[0];
2164*61046927SAndroid Build Coastguard Worker YYLTYPE loc = type->get_location();
2165*61046927SAndroid Build Coastguard Worker const char *name;
2166*61046927SAndroid Build Coastguard Worker
2167*61046927SAndroid Build Coastguard Worker const glsl_type *const constructor_type = type->glsl_type(& name, state);
2168*61046927SAndroid Build Coastguard Worker
2169*61046927SAndroid Build Coastguard Worker /* constructor_type can be NULL if a variable with the same name as the
2170*61046927SAndroid Build Coastguard Worker * structure has come into scope.
2171*61046927SAndroid Build Coastguard Worker */
2172*61046927SAndroid Build Coastguard Worker if (constructor_type == NULL) {
2173*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(& loc, state, "unknown type `%s' (structure name "
2174*61046927SAndroid Build Coastguard Worker "may be shadowed by a variable with the same name)",
2175*61046927SAndroid Build Coastguard Worker type->type_name);
2176*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2177*61046927SAndroid Build Coastguard Worker }
2178*61046927SAndroid Build Coastguard Worker
2179*61046927SAndroid Build Coastguard Worker
2180*61046927SAndroid Build Coastguard Worker /* Constructors for opaque types are illegal.
2181*61046927SAndroid Build Coastguard Worker *
2182*61046927SAndroid Build Coastguard Worker * From section 4.1.7 of the ARB_bindless_texture spec:
2183*61046927SAndroid Build Coastguard Worker *
2184*61046927SAndroid Build Coastguard Worker * "Samplers are represented using 64-bit integer handles, and may be "
2185*61046927SAndroid Build Coastguard Worker * converted to and from 64-bit integers using constructors."
2186*61046927SAndroid Build Coastguard Worker *
2187*61046927SAndroid Build Coastguard Worker * From section 4.1.X of the ARB_bindless_texture spec:
2188*61046927SAndroid Build Coastguard Worker *
2189*61046927SAndroid Build Coastguard Worker * "Images are represented using 64-bit integer handles, and may be
2190*61046927SAndroid Build Coastguard Worker * converted to and from 64-bit integers using constructors."
2191*61046927SAndroid Build Coastguard Worker */
2192*61046927SAndroid Build Coastguard Worker if (glsl_contains_atomic(constructor_type) ||
2193*61046927SAndroid Build Coastguard Worker (!state->has_bindless() && glsl_contains_opaque(constructor_type))) {
2194*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(& loc, state, "cannot construct %s type `%s'",
2195*61046927SAndroid Build Coastguard Worker state->has_bindless() ? "atomic" : "opaque",
2196*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type));
2197*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2198*61046927SAndroid Build Coastguard Worker }
2199*61046927SAndroid Build Coastguard Worker
2200*61046927SAndroid Build Coastguard Worker if (glsl_type_is_subroutine(constructor_type)) {
2201*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(& loc, state,
2202*61046927SAndroid Build Coastguard Worker "subroutine name cannot be a constructor `%s'",
2203*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type));
2204*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2205*61046927SAndroid Build Coastguard Worker }
2206*61046927SAndroid Build Coastguard Worker
2207*61046927SAndroid Build Coastguard Worker if (glsl_type_is_array(constructor_type)) {
2208*61046927SAndroid Build Coastguard Worker if (!state->check_version(state->allow_glsl_120_subset_in_110 ? 110 : 120,
2209*61046927SAndroid Build Coastguard Worker 300, &loc, "array constructors forbidden")) {
2210*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2211*61046927SAndroid Build Coastguard Worker }
2212*61046927SAndroid Build Coastguard Worker
2213*61046927SAndroid Build Coastguard Worker return process_array_constructor(instructions, constructor_type,
2214*61046927SAndroid Build Coastguard Worker & loc, &this->expressions, state);
2215*61046927SAndroid Build Coastguard Worker }
2216*61046927SAndroid Build Coastguard Worker
2217*61046927SAndroid Build Coastguard Worker
2218*61046927SAndroid Build Coastguard Worker /* There are two kinds of constructor calls. Constructors for arrays and
2219*61046927SAndroid Build Coastguard Worker * structures must have the exact number of arguments with matching types
2220*61046927SAndroid Build Coastguard Worker * in the correct order. These constructors follow essentially the same
2221*61046927SAndroid Build Coastguard Worker * type matching rules as functions.
2222*61046927SAndroid Build Coastguard Worker *
2223*61046927SAndroid Build Coastguard Worker * Constructors for built-in language types, such as mat4 and vec2, are
2224*61046927SAndroid Build Coastguard Worker * free form. The only requirements are that the parameters must provide
2225*61046927SAndroid Build Coastguard Worker * enough values of the correct scalar type and that no arguments are
2226*61046927SAndroid Build Coastguard Worker * given past the last used argument.
2227*61046927SAndroid Build Coastguard Worker *
2228*61046927SAndroid Build Coastguard Worker * When using the C-style initializer syntax from GLSL 4.20, constructors
2229*61046927SAndroid Build Coastguard Worker * must have the exact number of arguments with matching types in the
2230*61046927SAndroid Build Coastguard Worker * correct order.
2231*61046927SAndroid Build Coastguard Worker */
2232*61046927SAndroid Build Coastguard Worker if (glsl_type_is_struct(constructor_type)) {
2233*61046927SAndroid Build Coastguard Worker return process_record_constructor(instructions, constructor_type,
2234*61046927SAndroid Build Coastguard Worker &loc, &this->expressions,
2235*61046927SAndroid Build Coastguard Worker state);
2236*61046927SAndroid Build Coastguard Worker }
2237*61046927SAndroid Build Coastguard Worker
2238*61046927SAndroid Build Coastguard Worker if (!is_valid_constructor(constructor_type, state))
2239*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2240*61046927SAndroid Build Coastguard Worker
2241*61046927SAndroid Build Coastguard Worker /* Total number of components of the type being constructed. */
2242*61046927SAndroid Build Coastguard Worker const unsigned type_components = glsl_get_components(constructor_type);
2243*61046927SAndroid Build Coastguard Worker
2244*61046927SAndroid Build Coastguard Worker /* Number of components from parameters that have actually been
2245*61046927SAndroid Build Coastguard Worker * consumed. This is used to perform several kinds of error checking.
2246*61046927SAndroid Build Coastguard Worker */
2247*61046927SAndroid Build Coastguard Worker unsigned components_used = 0;
2248*61046927SAndroid Build Coastguard Worker
2249*61046927SAndroid Build Coastguard Worker unsigned matrix_parameters = 0;
2250*61046927SAndroid Build Coastguard Worker unsigned nonmatrix_parameters = 0;
2251*61046927SAndroid Build Coastguard Worker exec_list actual_parameters;
2252*61046927SAndroid Build Coastguard Worker
2253*61046927SAndroid Build Coastguard Worker foreach_list_typed(ast_node, ast, link, &this->expressions) {
2254*61046927SAndroid Build Coastguard Worker ir_rvalue *result = ast->hir(instructions, state);
2255*61046927SAndroid Build Coastguard Worker
2256*61046927SAndroid Build Coastguard Worker /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
2257*61046927SAndroid Build Coastguard Worker *
2258*61046927SAndroid Build Coastguard Worker * "It is an error to provide extra arguments beyond this
2259*61046927SAndroid Build Coastguard Worker * last used argument."
2260*61046927SAndroid Build Coastguard Worker */
2261*61046927SAndroid Build Coastguard Worker if (components_used >= type_components) {
2262*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(& loc, state, "too many parameters to `%s' "
2263*61046927SAndroid Build Coastguard Worker "constructor",
2264*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type));
2265*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2266*61046927SAndroid Build Coastguard Worker }
2267*61046927SAndroid Build Coastguard Worker
2268*61046927SAndroid Build Coastguard Worker if (!is_valid_constructor(result->type, state)) {
2269*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(& loc, state, "cannot construct `%s' from a "
2270*61046927SAndroid Build Coastguard Worker "non-numeric data type",
2271*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type));
2272*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2273*61046927SAndroid Build Coastguard Worker }
2274*61046927SAndroid Build Coastguard Worker
2275*61046927SAndroid Build Coastguard Worker /* Count the number of matrix and nonmatrix parameters. This
2276*61046927SAndroid Build Coastguard Worker * is used below to enforce some of the constructor rules.
2277*61046927SAndroid Build Coastguard Worker */
2278*61046927SAndroid Build Coastguard Worker if (glsl_type_is_matrix(result->type))
2279*61046927SAndroid Build Coastguard Worker matrix_parameters++;
2280*61046927SAndroid Build Coastguard Worker else
2281*61046927SAndroid Build Coastguard Worker nonmatrix_parameters++;
2282*61046927SAndroid Build Coastguard Worker
2283*61046927SAndroid Build Coastguard Worker actual_parameters.push_tail(result);
2284*61046927SAndroid Build Coastguard Worker components_used += glsl_get_components(result->type);
2285*61046927SAndroid Build Coastguard Worker }
2286*61046927SAndroid Build Coastguard Worker
2287*61046927SAndroid Build Coastguard Worker /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
2288*61046927SAndroid Build Coastguard Worker *
2289*61046927SAndroid Build Coastguard Worker * "It is an error to construct matrices from other matrices. This
2290*61046927SAndroid Build Coastguard Worker * is reserved for future use."
2291*61046927SAndroid Build Coastguard Worker */
2292*61046927SAndroid Build Coastguard Worker if (matrix_parameters > 0
2293*61046927SAndroid Build Coastguard Worker && glsl_type_is_matrix(constructor_type)
2294*61046927SAndroid Build Coastguard Worker && !state->check_version(120, 100, &loc,
2295*61046927SAndroid Build Coastguard Worker "cannot construct `%s' from a matrix",
2296*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type))) {
2297*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2298*61046927SAndroid Build Coastguard Worker }
2299*61046927SAndroid Build Coastguard Worker
2300*61046927SAndroid Build Coastguard Worker /* From page 50 (page 56 of the PDF) of the GLSL 1.50 spec:
2301*61046927SAndroid Build Coastguard Worker *
2302*61046927SAndroid Build Coastguard Worker * "If a matrix argument is given to a matrix constructor, it is
2303*61046927SAndroid Build Coastguard Worker * an error to have any other arguments."
2304*61046927SAndroid Build Coastguard Worker */
2305*61046927SAndroid Build Coastguard Worker if ((matrix_parameters > 0)
2306*61046927SAndroid Build Coastguard Worker && ((matrix_parameters + nonmatrix_parameters) > 1)
2307*61046927SAndroid Build Coastguard Worker && glsl_type_is_matrix(constructor_type)) {
2308*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(& loc, state, "for matrix `%s' constructor, "
2309*61046927SAndroid Build Coastguard Worker "matrix must be only parameter",
2310*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type));
2311*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2312*61046927SAndroid Build Coastguard Worker }
2313*61046927SAndroid Build Coastguard Worker
2314*61046927SAndroid Build Coastguard Worker /* From page 28 (page 34 of the PDF) of the GLSL 1.10 spec:
2315*61046927SAndroid Build Coastguard Worker *
2316*61046927SAndroid Build Coastguard Worker * "In these cases, there must be enough components provided in the
2317*61046927SAndroid Build Coastguard Worker * arguments to provide an initializer for every component in the
2318*61046927SAndroid Build Coastguard Worker * constructed value."
2319*61046927SAndroid Build Coastguard Worker */
2320*61046927SAndroid Build Coastguard Worker if (components_used < type_components && components_used != 1
2321*61046927SAndroid Build Coastguard Worker && matrix_parameters == 0) {
2322*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(& loc, state, "too few components to construct "
2323*61046927SAndroid Build Coastguard Worker "`%s'",
2324*61046927SAndroid Build Coastguard Worker glsl_get_type_name(constructor_type));
2325*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2326*61046927SAndroid Build Coastguard Worker }
2327*61046927SAndroid Build Coastguard Worker
2328*61046927SAndroid Build Coastguard Worker /* Matrices can never be consumed as is by any constructor but matrix
2329*61046927SAndroid Build Coastguard Worker * constructors. If the constructor type is not matrix, always break the
2330*61046927SAndroid Build Coastguard Worker * matrix up into a series of column vectors.
2331*61046927SAndroid Build Coastguard Worker */
2332*61046927SAndroid Build Coastguard Worker if (!glsl_type_is_matrix(constructor_type)) {
2333*61046927SAndroid Build Coastguard Worker foreach_in_list_safe(ir_rvalue, matrix, &actual_parameters) {
2334*61046927SAndroid Build Coastguard Worker if (!glsl_type_is_matrix(matrix->type))
2335*61046927SAndroid Build Coastguard Worker continue;
2336*61046927SAndroid Build Coastguard Worker
2337*61046927SAndroid Build Coastguard Worker /* Create a temporary containing the matrix. */
2338*61046927SAndroid Build Coastguard Worker ir_variable *var = new(ctx) ir_variable(matrix->type, "matrix_tmp",
2339*61046927SAndroid Build Coastguard Worker ir_var_temporary);
2340*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
2341*61046927SAndroid Build Coastguard Worker instructions->push_tail(
2342*61046927SAndroid Build Coastguard Worker new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
2343*61046927SAndroid Build Coastguard Worker matrix));
2344*61046927SAndroid Build Coastguard Worker var->constant_value = matrix->constant_expression_value(ctx);
2345*61046927SAndroid Build Coastguard Worker
2346*61046927SAndroid Build Coastguard Worker /* Replace the matrix with dereferences of its columns. */
2347*61046927SAndroid Build Coastguard Worker for (int i = 0; i < matrix->type->matrix_columns; i++) {
2348*61046927SAndroid Build Coastguard Worker matrix->insert_before(
2349*61046927SAndroid Build Coastguard Worker new (ctx) ir_dereference_array(var,
2350*61046927SAndroid Build Coastguard Worker new(ctx) ir_constant(i)));
2351*61046927SAndroid Build Coastguard Worker }
2352*61046927SAndroid Build Coastguard Worker matrix->remove();
2353*61046927SAndroid Build Coastguard Worker }
2354*61046927SAndroid Build Coastguard Worker }
2355*61046927SAndroid Build Coastguard Worker
2356*61046927SAndroid Build Coastguard Worker bool all_parameters_are_constant = true;
2357*61046927SAndroid Build Coastguard Worker
2358*61046927SAndroid Build Coastguard Worker /* Type cast each parameter and, if possible, fold constants.*/
2359*61046927SAndroid Build Coastguard Worker foreach_in_list_safe(ir_rvalue, ir, &actual_parameters) {
2360*61046927SAndroid Build Coastguard Worker const glsl_type *desired_type;
2361*61046927SAndroid Build Coastguard Worker
2362*61046927SAndroid Build Coastguard Worker /* From section 5.4.1 of the ARB_bindless_texture spec:
2363*61046927SAndroid Build Coastguard Worker *
2364*61046927SAndroid Build Coastguard Worker * "In the following four constructors, the low 32 bits of the sampler
2365*61046927SAndroid Build Coastguard Worker * type correspond to the .x component of the uvec2 and the high 32
2366*61046927SAndroid Build Coastguard Worker * bits correspond to the .y component."
2367*61046927SAndroid Build Coastguard Worker *
2368*61046927SAndroid Build Coastguard Worker * uvec2(any sampler type) // Converts a sampler type to a
2369*61046927SAndroid Build Coastguard Worker * // pair of 32-bit unsigned integers
2370*61046927SAndroid Build Coastguard Worker * any sampler type(uvec2) // Converts a pair of 32-bit unsigned integers to
2371*61046927SAndroid Build Coastguard Worker * // a sampler type
2372*61046927SAndroid Build Coastguard Worker * uvec2(any image type) // Converts an image type to a
2373*61046927SAndroid Build Coastguard Worker * // pair of 32-bit unsigned integers
2374*61046927SAndroid Build Coastguard Worker * any image type(uvec2) // Converts a pair of 32-bit unsigned integers to
2375*61046927SAndroid Build Coastguard Worker * // an image type
2376*61046927SAndroid Build Coastguard Worker */
2377*61046927SAndroid Build Coastguard Worker if (glsl_type_is_sampler(ir->type) || glsl_type_is_image(ir->type)) {
2378*61046927SAndroid Build Coastguard Worker /* Convert a sampler/image type to a pair of 32-bit unsigned
2379*61046927SAndroid Build Coastguard Worker * integers as defined by ARB_bindless_texture.
2380*61046927SAndroid Build Coastguard Worker */
2381*61046927SAndroid Build Coastguard Worker if (constructor_type != &glsl_type_builtin_uvec2) {
2382*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "sampler and image types can only "
2383*61046927SAndroid Build Coastguard Worker "be converted to a pair of 32-bit unsigned "
2384*61046927SAndroid Build Coastguard Worker "integers");
2385*61046927SAndroid Build Coastguard Worker }
2386*61046927SAndroid Build Coastguard Worker desired_type = &glsl_type_builtin_uvec2;
2387*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_sampler(constructor_type) ||
2388*61046927SAndroid Build Coastguard Worker glsl_type_is_image(constructor_type)) {
2389*61046927SAndroid Build Coastguard Worker /* Convert a pair of 32-bit unsigned integers to a sampler or image
2390*61046927SAndroid Build Coastguard Worker * type as defined by ARB_bindless_texture.
2391*61046927SAndroid Build Coastguard Worker */
2392*61046927SAndroid Build Coastguard Worker if (ir->type != &glsl_type_builtin_uvec2) {
2393*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "sampler and image types can only "
2394*61046927SAndroid Build Coastguard Worker "be converted from a pair of 32-bit unsigned "
2395*61046927SAndroid Build Coastguard Worker "integers");
2396*61046927SAndroid Build Coastguard Worker }
2397*61046927SAndroid Build Coastguard Worker desired_type = constructor_type;
2398*61046927SAndroid Build Coastguard Worker } else {
2399*61046927SAndroid Build Coastguard Worker desired_type =
2400*61046927SAndroid Build Coastguard Worker glsl_simple_type(constructor_type->base_type,
2401*61046927SAndroid Build Coastguard Worker ir->type->vector_elements,
2402*61046927SAndroid Build Coastguard Worker ir->type->matrix_columns);
2403*61046927SAndroid Build Coastguard Worker }
2404*61046927SAndroid Build Coastguard Worker
2405*61046927SAndroid Build Coastguard Worker ir_rvalue *result = convert_component(ir, desired_type);
2406*61046927SAndroid Build Coastguard Worker
2407*61046927SAndroid Build Coastguard Worker /* If the bindless packing constructors are used directly as function
2408*61046927SAndroid Build Coastguard Worker * params to bultin functions the compiler doesn't know what to do
2409*61046927SAndroid Build Coastguard Worker * with them. To avoid this make sure we always copy the results from
2410*61046927SAndroid Build Coastguard Worker * the pack to a temp first.
2411*61046927SAndroid Build Coastguard Worker */
2412*61046927SAndroid Build Coastguard Worker if (result->as_expression() &&
2413*61046927SAndroid Build Coastguard Worker result->as_expression()->operation == ir_unop_pack_sampler_2x32) {
2414*61046927SAndroid Build Coastguard Worker ir_variable *var =
2415*61046927SAndroid Build Coastguard Worker new(ctx) ir_variable(desired_type, "sampler_ctor",
2416*61046927SAndroid Build Coastguard Worker ir_var_temporary);
2417*61046927SAndroid Build Coastguard Worker instructions->push_tail(var);
2418*61046927SAndroid Build Coastguard Worker
2419*61046927SAndroid Build Coastguard Worker ir_dereference *lhs = new(ctx) ir_dereference_variable(var);
2420*61046927SAndroid Build Coastguard Worker ir_instruction *assignment = new(ctx) ir_assignment(lhs, result);
2421*61046927SAndroid Build Coastguard Worker instructions->push_tail(assignment);
2422*61046927SAndroid Build Coastguard Worker result = lhs;
2423*61046927SAndroid Build Coastguard Worker }
2424*61046927SAndroid Build Coastguard Worker
2425*61046927SAndroid Build Coastguard Worker /* Attempt to convert the parameter to a constant valued expression.
2426*61046927SAndroid Build Coastguard Worker * After doing so, track whether or not all the parameters to the
2427*61046927SAndroid Build Coastguard Worker * constructor are trivially constant valued expressions.
2428*61046927SAndroid Build Coastguard Worker */
2429*61046927SAndroid Build Coastguard Worker ir_rvalue *const constant = result->constant_expression_value(ctx);
2430*61046927SAndroid Build Coastguard Worker
2431*61046927SAndroid Build Coastguard Worker if (constant != NULL)
2432*61046927SAndroid Build Coastguard Worker result = constant;
2433*61046927SAndroid Build Coastguard Worker else
2434*61046927SAndroid Build Coastguard Worker all_parameters_are_constant = false;
2435*61046927SAndroid Build Coastguard Worker
2436*61046927SAndroid Build Coastguard Worker if (result != ir) {
2437*61046927SAndroid Build Coastguard Worker ir->replace_with(result);
2438*61046927SAndroid Build Coastguard Worker }
2439*61046927SAndroid Build Coastguard Worker }
2440*61046927SAndroid Build Coastguard Worker
2441*61046927SAndroid Build Coastguard Worker /* If all of the parameters are trivially constant, create a
2442*61046927SAndroid Build Coastguard Worker * constant representing the complete collection of parameters.
2443*61046927SAndroid Build Coastguard Worker */
2444*61046927SAndroid Build Coastguard Worker if (all_parameters_are_constant) {
2445*61046927SAndroid Build Coastguard Worker return new(ctx) ir_constant(constructor_type, &actual_parameters);
2446*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_scalar(constructor_type)) {
2447*61046927SAndroid Build Coastguard Worker return dereference_component((ir_rvalue *)
2448*61046927SAndroid Build Coastguard Worker actual_parameters.get_head_raw(),
2449*61046927SAndroid Build Coastguard Worker 0);
2450*61046927SAndroid Build Coastguard Worker } else if (glsl_type_is_vector(constructor_type)) {
2451*61046927SAndroid Build Coastguard Worker return emit_inline_vector_constructor(constructor_type,
2452*61046927SAndroid Build Coastguard Worker instructions,
2453*61046927SAndroid Build Coastguard Worker &actual_parameters,
2454*61046927SAndroid Build Coastguard Worker ctx);
2455*61046927SAndroid Build Coastguard Worker } else {
2456*61046927SAndroid Build Coastguard Worker assert(glsl_type_is_matrix(constructor_type));
2457*61046927SAndroid Build Coastguard Worker return emit_inline_matrix_constructor(constructor_type,
2458*61046927SAndroid Build Coastguard Worker instructions,
2459*61046927SAndroid Build Coastguard Worker &actual_parameters,
2460*61046927SAndroid Build Coastguard Worker ctx);
2461*61046927SAndroid Build Coastguard Worker }
2462*61046927SAndroid Build Coastguard Worker } else if (subexpressions[0]->oper == ast_field_selection) {
2463*61046927SAndroid Build Coastguard Worker return handle_method(instructions, state);
2464*61046927SAndroid Build Coastguard Worker } else {
2465*61046927SAndroid Build Coastguard Worker const ast_expression *id = subexpressions[0];
2466*61046927SAndroid Build Coastguard Worker const char *func_name = NULL;
2467*61046927SAndroid Build Coastguard Worker YYLTYPE loc = get_location();
2468*61046927SAndroid Build Coastguard Worker exec_list actual_parameters;
2469*61046927SAndroid Build Coastguard Worker ir_variable *sub_var = NULL;
2470*61046927SAndroid Build Coastguard Worker ir_rvalue *array_idx = NULL;
2471*61046927SAndroid Build Coastguard Worker
2472*61046927SAndroid Build Coastguard Worker process_parameters(instructions, &actual_parameters, &this->expressions,
2473*61046927SAndroid Build Coastguard Worker state);
2474*61046927SAndroid Build Coastguard Worker
2475*61046927SAndroid Build Coastguard Worker if (id->oper == ast_array_index) {
2476*61046927SAndroid Build Coastguard Worker array_idx = generate_array_index(ctx, instructions, state, loc,
2477*61046927SAndroid Build Coastguard Worker id->subexpressions[0],
2478*61046927SAndroid Build Coastguard Worker id->subexpressions[1], &func_name,
2479*61046927SAndroid Build Coastguard Worker &actual_parameters);
2480*61046927SAndroid Build Coastguard Worker } else if (id->oper == ast_identifier) {
2481*61046927SAndroid Build Coastguard Worker func_name = id->primary_expression.identifier;
2482*61046927SAndroid Build Coastguard Worker } else {
2483*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "function name is not an identifier");
2484*61046927SAndroid Build Coastguard Worker }
2485*61046927SAndroid Build Coastguard Worker
2486*61046927SAndroid Build Coastguard Worker /* an error was emitted earlier */
2487*61046927SAndroid Build Coastguard Worker if (!func_name)
2488*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2489*61046927SAndroid Build Coastguard Worker
2490*61046927SAndroid Build Coastguard Worker ir_function_signature *sig =
2491*61046927SAndroid Build Coastguard Worker match_function_by_name(func_name, &actual_parameters, state);
2492*61046927SAndroid Build Coastguard Worker
2493*61046927SAndroid Build Coastguard Worker ir_rvalue *value = NULL;
2494*61046927SAndroid Build Coastguard Worker if (sig == NULL) {
2495*61046927SAndroid Build Coastguard Worker sig = match_subroutine_by_name(func_name, &actual_parameters,
2496*61046927SAndroid Build Coastguard Worker state, &sub_var);
2497*61046927SAndroid Build Coastguard Worker }
2498*61046927SAndroid Build Coastguard Worker
2499*61046927SAndroid Build Coastguard Worker if (sig == NULL) {
2500*61046927SAndroid Build Coastguard Worker no_matching_function_error(func_name, &loc,
2501*61046927SAndroid Build Coastguard Worker &actual_parameters, state);
2502*61046927SAndroid Build Coastguard Worker value = ir_rvalue::error_value(ctx);
2503*61046927SAndroid Build Coastguard Worker } else if (!verify_parameter_modes(state, sig,
2504*61046927SAndroid Build Coastguard Worker actual_parameters,
2505*61046927SAndroid Build Coastguard Worker this->expressions)) {
2506*61046927SAndroid Build Coastguard Worker /* an error has already been emitted */
2507*61046927SAndroid Build Coastguard Worker value = ir_rvalue::error_value(ctx);
2508*61046927SAndroid Build Coastguard Worker } else if (sig->is_builtin() && strcmp(func_name, "ftransform") == 0) {
2509*61046927SAndroid Build Coastguard Worker /* ftransform refers to global variables, and we don't have any code
2510*61046927SAndroid Build Coastguard Worker * for remapping the variable references in the built-in shader.
2511*61046927SAndroid Build Coastguard Worker */
2512*61046927SAndroid Build Coastguard Worker ir_variable *mvp =
2513*61046927SAndroid Build Coastguard Worker state->symbols->get_variable("gl_ModelViewProjectionMatrix");
2514*61046927SAndroid Build Coastguard Worker ir_variable *vtx = state->symbols->get_variable("gl_Vertex");
2515*61046927SAndroid Build Coastguard Worker value = new(ctx) ir_expression(ir_binop_mul, &glsl_type_builtin_vec4,
2516*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_variable(mvp),
2517*61046927SAndroid Build Coastguard Worker new(ctx) ir_dereference_variable(vtx));
2518*61046927SAndroid Build Coastguard Worker } else {
2519*61046927SAndroid Build Coastguard Worker bool is_begin_interlock = false;
2520*61046927SAndroid Build Coastguard Worker bool is_end_interlock = false;
2521*61046927SAndroid Build Coastguard Worker if (sig->is_builtin() &&
2522*61046927SAndroid Build Coastguard Worker state->stage == MESA_SHADER_FRAGMENT &&
2523*61046927SAndroid Build Coastguard Worker state->ARB_fragment_shader_interlock_enable) {
2524*61046927SAndroid Build Coastguard Worker is_begin_interlock = strcmp(func_name, "beginInvocationInterlockARB") == 0;
2525*61046927SAndroid Build Coastguard Worker is_end_interlock = strcmp(func_name, "endInvocationInterlockARB") == 0;
2526*61046927SAndroid Build Coastguard Worker }
2527*61046927SAndroid Build Coastguard Worker
2528*61046927SAndroid Build Coastguard Worker if (sig->is_builtin() &&
2529*61046927SAndroid Build Coastguard Worker ((state->stage == MESA_SHADER_TESS_CTRL &&
2530*61046927SAndroid Build Coastguard Worker strcmp(func_name, "barrier") == 0) ||
2531*61046927SAndroid Build Coastguard Worker is_begin_interlock || is_end_interlock)) {
2532*61046927SAndroid Build Coastguard Worker if (state->current_function == NULL ||
2533*61046927SAndroid Build Coastguard Worker strcmp(state->current_function->function_name(), "main") != 0) {
2534*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
2535*61046927SAndroid Build Coastguard Worker "%s() may only be used in main()", func_name);
2536*61046927SAndroid Build Coastguard Worker }
2537*61046927SAndroid Build Coastguard Worker
2538*61046927SAndroid Build Coastguard Worker if (state->found_return) {
2539*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
2540*61046927SAndroid Build Coastguard Worker "%s() may not be used after return", func_name);
2541*61046927SAndroid Build Coastguard Worker }
2542*61046927SAndroid Build Coastguard Worker
2543*61046927SAndroid Build Coastguard Worker if (instructions != &state->current_function->body) {
2544*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
2545*61046927SAndroid Build Coastguard Worker "%s() may not be used in control flow", func_name);
2546*61046927SAndroid Build Coastguard Worker }
2547*61046927SAndroid Build Coastguard Worker }
2548*61046927SAndroid Build Coastguard Worker
2549*61046927SAndroid Build Coastguard Worker /* There can be only one begin/end interlock pair in the function. */
2550*61046927SAndroid Build Coastguard Worker if (is_begin_interlock) {
2551*61046927SAndroid Build Coastguard Worker if (state->found_begin_interlock)
2552*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
2553*61046927SAndroid Build Coastguard Worker "beginInvocationInterlockARB may not be used twice");
2554*61046927SAndroid Build Coastguard Worker state->found_begin_interlock = true;
2555*61046927SAndroid Build Coastguard Worker } else if (is_end_interlock) {
2556*61046927SAndroid Build Coastguard Worker if (!state->found_begin_interlock)
2557*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
2558*61046927SAndroid Build Coastguard Worker "endInvocationInterlockARB may not be used "
2559*61046927SAndroid Build Coastguard Worker "before beginInvocationInterlockARB");
2560*61046927SAndroid Build Coastguard Worker if (state->found_end_interlock)
2561*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state,
2562*61046927SAndroid Build Coastguard Worker "endInvocationInterlockARB may not be used twice");
2563*61046927SAndroid Build Coastguard Worker state->found_end_interlock = true;
2564*61046927SAndroid Build Coastguard Worker }
2565*61046927SAndroid Build Coastguard Worker
2566*61046927SAndroid Build Coastguard Worker value = generate_call(instructions, sig, &actual_parameters, sub_var,
2567*61046927SAndroid Build Coastguard Worker array_idx, state);
2568*61046927SAndroid Build Coastguard Worker if (!value) {
2569*61046927SAndroid Build Coastguard Worker ir_variable *const tmp = new(ctx) ir_variable(&glsl_type_builtin_void,
2570*61046927SAndroid Build Coastguard Worker "void_var",
2571*61046927SAndroid Build Coastguard Worker ir_var_temporary);
2572*61046927SAndroid Build Coastguard Worker instructions->push_tail(tmp);
2573*61046927SAndroid Build Coastguard Worker value = new(ctx) ir_dereference_variable(tmp);
2574*61046927SAndroid Build Coastguard Worker }
2575*61046927SAndroid Build Coastguard Worker }
2576*61046927SAndroid Build Coastguard Worker
2577*61046927SAndroid Build Coastguard Worker return value;
2578*61046927SAndroid Build Coastguard Worker }
2579*61046927SAndroid Build Coastguard Worker
2580*61046927SAndroid Build Coastguard Worker unreachable("not reached");
2581*61046927SAndroid Build Coastguard Worker }
2582*61046927SAndroid Build Coastguard Worker
2583*61046927SAndroid Build Coastguard Worker bool
has_sequence_subexpression() const2584*61046927SAndroid Build Coastguard Worker ast_function_expression::has_sequence_subexpression() const
2585*61046927SAndroid Build Coastguard Worker {
2586*61046927SAndroid Build Coastguard Worker foreach_list_typed(const ast_node, ast, link, &this->expressions) {
2587*61046927SAndroid Build Coastguard Worker if (ast->has_sequence_subexpression())
2588*61046927SAndroid Build Coastguard Worker return true;
2589*61046927SAndroid Build Coastguard Worker }
2590*61046927SAndroid Build Coastguard Worker
2591*61046927SAndroid Build Coastguard Worker return false;
2592*61046927SAndroid Build Coastguard Worker }
2593*61046927SAndroid Build Coastguard Worker
2594*61046927SAndroid Build Coastguard Worker ir_rvalue *
hir(exec_list * instructions,struct _mesa_glsl_parse_state * state)2595*61046927SAndroid Build Coastguard Worker ast_aggregate_initializer::hir(exec_list *instructions,
2596*61046927SAndroid Build Coastguard Worker struct _mesa_glsl_parse_state *state)
2597*61046927SAndroid Build Coastguard Worker {
2598*61046927SAndroid Build Coastguard Worker void *ctx = state;
2599*61046927SAndroid Build Coastguard Worker YYLTYPE loc = this->get_location();
2600*61046927SAndroid Build Coastguard Worker
2601*61046927SAndroid Build Coastguard Worker if (!this->constructor_type) {
2602*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "type of C-style initializer unknown");
2603*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2604*61046927SAndroid Build Coastguard Worker }
2605*61046927SAndroid Build Coastguard Worker const glsl_type *const constructor_type = this->constructor_type;
2606*61046927SAndroid Build Coastguard Worker
2607*61046927SAndroid Build Coastguard Worker if (!state->has_420pack()) {
2608*61046927SAndroid Build Coastguard Worker _mesa_glsl_error(&loc, state, "C-style initialization requires the "
2609*61046927SAndroid Build Coastguard Worker "GL_ARB_shading_language_420pack extension");
2610*61046927SAndroid Build Coastguard Worker return ir_rvalue::error_value(ctx);
2611*61046927SAndroid Build Coastguard Worker }
2612*61046927SAndroid Build Coastguard Worker
2613*61046927SAndroid Build Coastguard Worker if (glsl_type_is_array(constructor_type)) {
2614*61046927SAndroid Build Coastguard Worker return process_array_constructor(instructions, constructor_type, &loc,
2615*61046927SAndroid Build Coastguard Worker &this->expressions, state);
2616*61046927SAndroid Build Coastguard Worker }
2617*61046927SAndroid Build Coastguard Worker
2618*61046927SAndroid Build Coastguard Worker if (glsl_type_is_struct(constructor_type)) {
2619*61046927SAndroid Build Coastguard Worker return process_record_constructor(instructions, constructor_type, &loc,
2620*61046927SAndroid Build Coastguard Worker &this->expressions, state);
2621*61046927SAndroid Build Coastguard Worker }
2622*61046927SAndroid Build Coastguard Worker
2623*61046927SAndroid Build Coastguard Worker return process_vec_mat_constructor(instructions, constructor_type, &loc,
2624*61046927SAndroid Build Coastguard Worker &this->expressions, state);
2625*61046927SAndroid Build Coastguard Worker }
2626